Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID updates from Jiri Kosina:

- Integrated Sensor Hub support (Cherrytrail+) from Srinivas Pandruvada

- Big cleanup of Wacom driver; namely it's now using devres, and the
standardized LED API so that libinput doesn't need to have root
access any more, with substantial amount of other cleanups
piggy-backing on top. All this from Benjamin Tissoires

- Report descriptor parsing would now ignore and out-of-range System
controls in case of the application actually being System Control.
This fixes quite some issues with several devices, and allows us to
remove a few ->report_fixup callbacks. From Benjamin Tissoires

- ... a lot of other assorted small fixes and device ID additions

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: (76 commits)
HID: add missing \n to end of dev_warn messages
HID: alps: fix multitouch cursor issue
HID: hid-logitech: Documentation updates/corrections
HID: hid-logitech: Improve Wingman Formula Force GP support
HID: hid-logitech: Rewrite of descriptor for all DF wheels
HID: hid-logitech: Compute combined pedals value
HID: hid-logitech: Add combined pedal support Logitech wheels
HID: hid-logitech: Introduce control for combined pedals feature
HID: sony: Update copyright and add Dualshock 4 rate control note
HID: sony: Defer the initial USB Sixaxis output report
HID: sony: Relax duplicate checking for USB-only devices
Revert "HID: microsoft: fix invalid rdesc for 3k kbd"
HID: alps: fix error return code in alps_input_configured()
HID: alps: fix stick device not working after resume
HID: support for keyboard - Corsair STRAFE
HID: alps: Fix memory leak
HID: uclogic: Add support for UC-Logic TWHA60 v3
HID: uclogic: Override constant descriptors
HID: uclogic: Support UGTizer GP0610 partially
HID: uclogic: Add support for several more tablets
...

+9648 -675
+15
Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
··· 35 35 DF-EX <*--------> G25 <-> G27 36 36 DF-EX <*----------------> G27 37 37 38 + G29: 39 + DF-EX <*> DFP <-> G25 <-> G27 <-> G29 40 + DF-EX <*--------> G25 <-> G27 <-> G29 41 + DF-EX <*----------------> G27 <-> G29 42 + DF-EX <*------------------------> G29 43 + 38 44 DFGT: 39 45 DF-EX <*> DFP <-> DFGT 40 46 DF-EX <*--------> DFGT ··· 56 50 alternate mode the wheel might be switched to. 57 51 It is a read-only value. 58 52 This entry is not created for devices that have only one mode. 53 + 54 + What: /sys/bus/hid/drivers/logitech/<dev>/combine_pedals 55 + Date: Sep 2016 56 + KernelVersion: 4.9 57 + Contact: Simon Wood <simon@mungewell.org> 58 + Description: Controls whether a combined value of accelerator and brake is 59 + reported on the Y axis of the controller. Useful for older games 60 + which can do not work with separate accelerator/brake axis. 61 + Off ('0') by default, enabled by setting '1'.
+5
Documentation/ABI/testing/sysfs-driver-wacom
··· 24 24 Date: August 2014 25 25 Contact: linux-input@vger.kernel.org 26 26 Description: 27 + <obsoleted by the LED class API now exported by the driver> 27 28 Writing to this file sets the status LED luminance (1..127) 28 29 when the stylus does not touch the tablet surface, and no 29 30 button is pressed on the stylus. This luminance level is ··· 34 33 Date: August 2014 35 34 Contact: linux-input@vger.kernel.org 36 35 Description: 36 + <obsoleted by the LED class API now exported by the driver> 37 37 Writing to this file sets the status LED luminance (1..127) 38 38 when the stylus touches the tablet surface, or any button is 39 39 pressed on the stylus. ··· 43 41 Date: August 2014 44 42 Contact: linux-input@vger.kernel.org 45 43 Description: 44 + <obsoleted by the LED class API now exported by the driver> 46 45 Writing to this file sets which one of the four (for Intuos 4 47 46 and Intuos 5) or of the right four (for Cintiq 21UX2 and Cintiq 48 47 24HD) status LEDs is active (0..3). The other three LEDs on the ··· 53 50 Date: August 2014 54 51 Contact: linux-input@vger.kernel.org 55 52 Description: 53 + <obsoleted by the LED class API now exported by the driver> 56 54 Writing to this file sets which one of the left four (for Cintiq 21UX2 57 55 and Cintiq 24HD) status LEDs is active (0..3). The other three LEDs on 58 56 the left are always inactive. ··· 95 91 Date: July 2015 96 92 Contact: linux-input@vger.kernel.org 97 93 Description: 94 + <obsoleted by the LED class API now exported by the driver> 98 95 Reading from this file reports the mode status of the 99 96 remote as indicated by the LED lights on the device. If no 100 97 reports have been received from the paired device, reading
+454
Documentation/hid/intel-ish-hid.txt
··· 1 + Intel Integrated Sensor Hub (ISH) 2 + =============================== 3 + 4 + A sensor hub enables the ability to offload sensor polling and algorithm 5 + processing to a dedicated low power co-processor. This allows the core 6 + processor to go into low power modes more often, resulting in the increased 7 + battery life. 8 + 9 + There are many vendors providing external sensor hubs confirming to HID 10 + Sensor usage tables, and used in several tablets, 2 in 1 convertible laptops 11 + and embedded products. Linux had this support since Linux 3.9. 12 + 13 + Intel® introduced integrated sensor hubs as a part of the SoC starting from 14 + Cherry Trail and now supported on multiple generations of CPU packages. There 15 + are many commercial devices already shipped with Integrated Sensor Hubs (ISH). 16 + These ISH also comply to HID sensor specification, but the difference is the 17 + transport protocol used for communication. The current external sensor hubs 18 + mainly use HID over i2C or USB. But ISH doesn't use either i2c or USB. 19 + 20 + 1. Overview 21 + 22 + Using a analogy with a usbhid implementation, the ISH follows a similar model 23 + for a very high speed communication: 24 + 25 + ----------------- ---------------------- 26 + | USB HID | --> | ISH HID | 27 + ----------------- ---------------------- 28 + ----------------- ---------------------- 29 + | USB protocol | --> | ISH Transport | 30 + ----------------- ---------------------- 31 + ----------------- ---------------------- 32 + | EHCI/XHCI | --> | ISH IPC | 33 + ----------------- ---------------------- 34 + PCI PCI 35 + ----------------- ---------------------- 36 + |Host controller| --> | ISH processor | 37 + ----------------- ---------------------- 38 + USB Link 39 + ----------------- ---------------------- 40 + | USB End points| --> | ISH Clients | 41 + ----------------- ---------------------- 42 + 43 + Like USB protocol provides a method for device enumeration, link management 44 + and user data encapsulation, the ISH also provides similar services. But it is 45 + very light weight tailored to manage and communicate with ISH client 46 + applications implemented in the firmware. 47 + 48 + The ISH allows multiple sensor management applications executing in the 49 + firmware. Like USB endpoints the messaging can be to/from a client. As part of 50 + enumeration process, these clients are identified. These clients can be simple 51 + HID sensor applications, sensor calibration application or senor firmware 52 + update application. 53 + 54 + The implementation model is similar, like USB bus, ISH transport is also 55 + implemented as a bus. Each client application executing in the ISH processor 56 + is registered as a device on this bus. The driver, which binds each device 57 + (ISH HID driver) identifies the device type and registers with the hid core. 58 + 59 + 2. ISH Implementation: Block Diagram 60 + 61 + --------------------------- 62 + | User Space Applications | 63 + --------------------------- 64 + 65 + ----------------IIO ABI---------------- 66 + -------------------------- 67 + | IIO Sensor Drivers | 68 + -------------------------- 69 + -------------------------- 70 + | IIO core | 71 + -------------------------- 72 + -------------------------- 73 + | HID Sensor Hub MFD | 74 + -------------------------- 75 + -------------------------- 76 + | HID Core | 77 + -------------------------- 78 + -------------------------- 79 + | HID over ISH Client | 80 + -------------------------- 81 + -------------------------- 82 + | ISH Transport (ISHTP) | 83 + -------------------------- 84 + -------------------------- 85 + | IPC Drivers | 86 + -------------------------- 87 + OS 88 + ---------------- PCI ----------------- 89 + Hardware + Firmware 90 + ---------------------------- 91 + | ISH Hardware/Firmware(FW) | 92 + ---------------------------- 93 + 94 + 3. High level processing in above blocks 95 + 96 + 3.1 Hardware Interface 97 + 98 + The ISH is exposed as "Non-VGA unclassified PCI device" to the host. The PCI 99 + product and vendor IDs are changed from different generations of processors. So 100 + the source code which enumerate drivers needs to update from generation to 101 + generation. 102 + 103 + 3.2 Inter Processor Communication (IPC) driver 104 + Location: drivers/hid/intel-ish-hid/ipc 105 + 106 + The IPC message used memory mapped I/O. The registers are defined in 107 + hw-ish-regs.h. 108 + 109 + 3.2.1 IPC/FW message types 110 + 111 + There are two types of messages, one for management of link and other messages 112 + are to and from transport layers. 113 + 114 + TX and RX of Transport messages 115 + 116 + A set of memory mapped register offers support of multi byte messages TX and 117 + RX (E.g.IPC_REG_ISH2HOST_MSG, IPC_REG_HOST2ISH_MSG). The IPC layer maintains 118 + internal queues to sequence messages and send them in order to the FW. 119 + Optionally the caller can register handler to get notification of completion. 120 + A door bell mechanism is used in messaging to trigger processing in host and 121 + client firmware side. When ISH interrupt handler is called, the ISH2HOST 122 + doorbell register is used by host drivers to determine that the interrupt 123 + is for ISH. 124 + 125 + Each side has 32 32-bit message registers and a 32-bit doorbell. Doorbell 126 + register has the following format: 127 + Bits 0..6: fragment length (7 bits are used) 128 + Bits 10..13: encapsulated protocol 129 + Bits 16..19: management command (for IPC management protocol) 130 + Bit 31: doorbell trigger (signal H/W interrupt to the other side) 131 + Other bits are reserved, should be 0. 132 + 133 + 3.2.2 Transport layer interface 134 + 135 + To abstract HW level IPC communication, a set of callbacks are registered. 136 + The transport layer uses them to send and receive messages. 137 + Refer to struct ishtp_hw_ops for callbacks. 138 + 139 + 3.3 ISH Transport layer 140 + Location: drivers/hid/intel-ish-hid/ishtp/ 141 + 142 + 3.3.1 A Generic Transport Layer 143 + 144 + The transport layer is a bi-directional protocol, which defines: 145 + - Set of commands to start, stop, connect, disconnect and flow control 146 + (ishtp/hbm.h) for details 147 + - A flow control mechanism to avoid buffer overflows 148 + 149 + This protocol resembles bus messages described in the following document: 150 + http://www.intel.com/content/dam/www/public/us/en/documents/technical-\ 151 + specifications/dcmi-hi-1-0-spec.pdf "Chapter 7: Bus Message Layer" 152 + 153 + 3.3.2 Connection and Flow Control Mechanism 154 + 155 + Each FW client and a protocol is identified by an UUID. In order to communicate 156 + to a FW client, a connection must be established using connect request and 157 + response bus messages. If successful, a pair (host_client_id and fw_client_id) 158 + will identify the connection. 159 + 160 + Once connection is established, peers send each other flow control bus messages 161 + independently. Every peer may send a message only if it has received a 162 + flow-control credit before. Once it sent a message, it may not send another one 163 + before receiving the next flow control credit. 164 + Either side can send disconnect request bus message to end communication. Also 165 + the link will be dropped if major FW reset occurs. 166 + 167 + 3.3.3 Peer to Peer data transfer 168 + 169 + Peer to Peer data transfer can happen with or without using DMA. Depending on 170 + the sensor bandwidth requirement DMA can be enabled by using module parameter 171 + ishtp_use_dma under intel_ishtp. 172 + 173 + Each side (host and FW) manages its DMA transfer memory independently. When an 174 + ISHTP client from either host or FW side wants to send something, it decides 175 + whether to send over IPC or over DMA; for each transfer the decision is 176 + independent. The sending side sends DMA_XFER message when the message is in 177 + the respective host buffer (TX when host client sends, RX when FW client 178 + sends). The recipient of DMA message responds with DMA_XFER_ACK, indicating 179 + the sender that the memory region for that message may be reused. 180 + 181 + DMA initialization is started with host sending DMA_ALLOC_NOTIFY bus message 182 + (that includes RX buffer) and FW responds with DMA_ALLOC_NOTIFY_ACK. 183 + Additionally to DMA address communication, this sequence checks capabilities: 184 + if thw host doesn't support DMA, then it won't send DMA allocation, so FW can't 185 + send DMA; if FW doesn't support DMA then it won't respond with 186 + DMA_ALLOC_NOTIFY_ACK, in which case host will not use DMA transfers. 187 + Here ISH acts as busmaster DMA controller. Hence when host sends DMA_XFER, 188 + it's request to do host->ISH DMA transfer; when FW sends DMA_XFER, it means 189 + that it already did DMA and the message resides at host. Thus, DMA_XFER 190 + and DMA_XFER_ACK act as ownership indicators. 191 + 192 + At initial state all outgoing memory belongs to the sender (TX to host, RX to 193 + FW), DMA_XFER transfers ownership on the region that contains ISHTP message to 194 + the receiving side, DMA_XFER_ACK returns ownership to the sender. A sender 195 + needs not wait for previous DMA_XFER to be ack'ed, and may send another message 196 + as long as remaining continuous memory in its ownership is enough. 197 + In principle, multiple DMA_XFER and DMA_XFER_ACK messages may be sent at once 198 + (up to IPC MTU), thus allowing for interrupt throttling. 199 + Currently, ISH FW decides to send over DMA if ISHTP message is more than 3 IPC 200 + fragments and via IPC otherwise. 201 + 202 + 3.3.4 Ring Buffers 203 + 204 + When a client initiate a connection, a ring or RX and TX buffers are allocated. 205 + The size of ring can be specified by the client. HID client set 16 and 32 for 206 + TX and RX buffers respectively. On send request from client, the data to be 207 + sent is copied to one of the send ring buffer and scheduled to be sent using 208 + bus message protocol. These buffers are required because the FW may have not 209 + have processed the last message and may not have enough flow control credits 210 + to send. Same thing holds true on receive side and flow control is required. 211 + 212 + 3.3.5 Host Enumeration 213 + 214 + The host enumeration bus command allow discovery of clients present in the FW. 215 + There can be multiple sensor clients and clients for calibration function. 216 + 217 + To ease in implantation and allow independent driver handle each client 218 + this transport layer takes advantage of Linux Bus driver model. Each 219 + client is registered as device on the the transport bus (ishtp bus). 220 + 221 + Enumeration sequence of messages: 222 + - Host sends HOST_START_REQ_CMD, indicating that host ISHTP layer is up. 223 + - FW responds with HOST_START_RES_CMD 224 + - Host sends HOST_ENUM_REQ_CMD (enumerate FW clients) 225 + - FW responds with HOST_ENUM_RES_CMD that includes bitmap of available FW 226 + client IDs 227 + - For each FW ID found in that bitmap host sends 228 + HOST_CLIENT_PROPERTIES_REQ_CMD 229 + - FW responds with HOST_CLIENT_PROPERTIES_RES_CMD. Properties include UUID, 230 + max ISHTP message size, etc. 231 + - Once host received properties for that last discovered client, it considers 232 + ISHTP device fully functional (and allocates DMA buffers) 233 + 234 + 3.4 HID over ISH Client 235 + Location: drivers/hid/intel-ish-hid 236 + 237 + The ISHTP client driver is responsible for: 238 + - enumerate HID devices under FW ISH client 239 + - Get Report descriptor 240 + - Register with HID core as a LL driver 241 + - Process Get/Set feature request 242 + - Get input reports 243 + 244 + 3.5 HID Sensor Hub MFD and IIO sensor drivers 245 + 246 + The functionality in these drivers is the same as an external sensor hub. 247 + Refer to 248 + Documentation/hid/hid-sensor.txt for HID sensor 249 + Documentation/ABI/testing/sysfs-bus-iio for IIO ABIs to user space 250 + 251 + 3.6 End to End HID transport Sequence Diagram 252 + 253 + HID-ISH-CLN ISHTP IPC HW 254 + | | | | 255 + | | |-----WAKE UP------------------>| 256 + | | | | 257 + | | |-----HOST READY--------------->| 258 + | | | | 259 + | | |<----MNG_RESET_NOTIFY_ACK----- | 260 + | | | | 261 + | |<----ISHTP_START------ | | 262 + | | | | 263 + | |<-----------------HOST_START_RES_CMD-------------------| 264 + | | | | 265 + | |------------------QUERY_SUBSCRIBER-------------------->| 266 + | | | | 267 + | |------------------HOST_ENUM_REQ_CMD------------------->| 268 + | | | | 269 + | |<-----------------HOST_ENUM_RES_CMD--------------------| 270 + | | | | 271 + | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| 272 + | | | | 273 + | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| 274 + | Create new device on in ishtp bus | | 275 + | | | | 276 + | |------------------HOST_CLIENT_PROPERTIES_REQ_CMD------>| 277 + | | | | 278 + | |<-----------------HOST_CLIENT_PROPERTIES_RES_CMD-------| 279 + | Create new device on in ishtp bus | | 280 + | | | | 281 + | |--Repeat HOST_CLIENT_PROPERTIES_REQ_CMD-till last one--| 282 + | | | | 283 + probed() 284 + |----ishtp_cl_connect-->|----------------- CLIENT_CONNECT_REQ_CMD-------------->| 285 + | | | | 286 + | |<----------------CLIENT_CONNECT_RES_CMD----------------| 287 + | | | | 288 + |register event callback| | | 289 + | | | | 290 + |ishtp_cl_send( 291 + HOSTIF_DM_ENUM_DEVICES) |----------fill ishtp_msg_hdr struct write to HW----- >| 292 + | | | | 293 + | | |<-----IRQ(IPC_PROTOCOL_ISHTP---| 294 + | | | | 295 + |<--ENUM_DEVICE RSP-----| | | 296 + | | | | 297 + for each enumerated device 298 + |ishtp_cl_send( 299 + HOSTIF_GET_HID_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW--- >| 300 + | | | | 301 + ...Response 302 + | | | | 303 + for each enumerated device 304 + |ishtp_cl_send( 305 + HOSTIF_GET_REPORT_DESCRIPTOR |----------fill ishtp_msg_hdr struct write to HW- >| 306 + | | | | 307 + | | | | 308 + hid_allocate_device 309 + | | | | 310 + hid_add_device | | | 311 + | | | | 312 + 313 + 314 + 3.7 ISH Debugging 315 + 316 + To debug ISH, event tracing mechanism is used. To enable debug logs 317 + echo 1 > /sys/kernel/debug/tracing/events/intel_ish/enable 318 + cat sys/kernel/debug/tracing/trace 319 + 320 + 3.8 ISH IIO sysfs Example on Lenovo thinkpad Yoga 260 321 + 322 + root@otcpl-ThinkPad-Yoga-260:~# tree -l /sys/bus/iio/devices/ 323 + /sys/bus/iio/devices/ 324 + ├── iio:device0 -> ../../../devices/0044:8086:22D8.0001/HID-SENSOR-200073.9.auto/iio:device0 325 + │   ├── buffer 326 + │   │   ├── enable 327 + │   │   ├── length 328 + │   │   └── watermark 329 + ... 330 + │   ├── in_accel_hysteresis 331 + │   ├── in_accel_offset 332 + │   ├── in_accel_sampling_frequency 333 + │   ├── in_accel_scale 334 + │   ├── in_accel_x_raw 335 + │   ├── in_accel_y_raw 336 + │   ├── in_accel_z_raw 337 + │   ├── name 338 + │   ├── scan_elements 339 + │   │   ├── in_accel_x_en 340 + │   │   ├── in_accel_x_index 341 + │   │   ├── in_accel_x_type 342 + │   │   ├── in_accel_y_en 343 + │   │   ├── in_accel_y_index 344 + │   │   ├── in_accel_y_type 345 + │   │   ├── in_accel_z_en 346 + │   │   ├── in_accel_z_index 347 + │   │   └── in_accel_z_type 348 + ... 349 + │   │   ├── devices 350 + │   │   │   │   ├── buffer 351 + │   │   │   │   │   ├── enable 352 + │   │   │   │   │   ├── length 353 + │   │   │   │   │   └── watermark 354 + │   │   │   │   ├── dev 355 + │   │   │   │   ├── in_intensity_both_raw 356 + │   │   │   │   ├── in_intensity_hysteresis 357 + │   │   │   │   ├── in_intensity_offset 358 + │   │   │   │   ├── in_intensity_sampling_frequency 359 + │   │   │   │   ├── in_intensity_scale 360 + │   │   │   │   ├── name 361 + │   │   │   │   ├── scan_elements 362 + │   │   │   │   │   ├── in_intensity_both_en 363 + │   │   │   │   │   ├── in_intensity_both_index 364 + │   │   │   │   │   └── in_intensity_both_type 365 + │   │   │   │   ├── trigger 366 + │   │   │   │   │   └── current_trigger 367 + ... 368 + │   │   │   │   ├── buffer 369 + │   │   │   │   │   ├── enable 370 + │   │   │   │   │   ├── length 371 + │   │   │   │   │   └── watermark 372 + │   │   │   │   ├── dev 373 + │   │   │   │   ├── in_magn_hysteresis 374 + │   │   │   │   ├── in_magn_offset 375 + │   │   │   │   ├── in_magn_sampling_frequency 376 + │   │   │   │   ├── in_magn_scale 377 + │   │   │   │   ├── in_magn_x_raw 378 + │   │   │   │   ├── in_magn_y_raw 379 + │   │   │   │   ├── in_magn_z_raw 380 + │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_raw 381 + │   │   │   │   ├── in_rot_hysteresis 382 + │   │   │   │   ├── in_rot_offset 383 + │   │   │   │   ├── in_rot_sampling_frequency 384 + │   │   │   │   ├── in_rot_scale 385 + │   │   │   │   ├── name 386 + ... 387 + │   │   │   │   ├── scan_elements 388 + │   │   │   │   │   ├── in_magn_x_en 389 + │   │   │   │   │   ├── in_magn_x_index 390 + │   │   │   │   │   ├── in_magn_x_type 391 + │   │   │   │   │   ├── in_magn_y_en 392 + │   │   │   │   │   ├── in_magn_y_index 393 + │   │   │   │   │   ├── in_magn_y_type 394 + │   │   │   │   │   ├── in_magn_z_en 395 + │   │   │   │   │   ├── in_magn_z_index 396 + │   │   │   │   │   ├── in_magn_z_type 397 + │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_en 398 + │   │   │   │   │   ├── in_rot_from_north_magnetic_tilt_comp_index 399 + │   │   │   │   │   └── in_rot_from_north_magnetic_tilt_comp_type 400 + │   │   │   │   ├── trigger 401 + │   │   │   │   │   └── current_trigger 402 + ... 403 + │   │   │   │   ├── buffer 404 + │   │   │   │   │   ├── enable 405 + │   │   │   │   │   ├── length 406 + │   │   │   │   │   └── watermark 407 + │   │   │   │   ├── dev 408 + │   │   │   │   ├── in_anglvel_hysteresis 409 + │   │   │   │   ├── in_anglvel_offset 410 + │   │   │   │   ├── in_anglvel_sampling_frequency 411 + │   │   │   │   ├── in_anglvel_scale 412 + │   │   │   │   ├── in_anglvel_x_raw 413 + │   │   │   │   ├── in_anglvel_y_raw 414 + │   │   │   │   ├── in_anglvel_z_raw 415 + │   │   │   │   ├── name 416 + │   │   │   │   ├── scan_elements 417 + │   │   │   │   │   ├── in_anglvel_x_en 418 + │   │   │   │   │   ├── in_anglvel_x_index 419 + │   │   │   │   │   ├── in_anglvel_x_type 420 + │   │   │   │   │   ├── in_anglvel_y_en 421 + │   │   │   │   │   ├── in_anglvel_y_index 422 + │   │   │   │   │   ├── in_anglvel_y_type 423 + │   │   │   │   │   ├── in_anglvel_z_en 424 + │   │   │   │   │   ├── in_anglvel_z_index 425 + │   │   │   │   │   └── in_anglvel_z_type 426 + │   │   │   │   ├── trigger 427 + │   │   │   │   │   └── current_trigger 428 + ... 429 + │   │   │   │   ├── buffer 430 + │   │   │   │   │   ├── enable 431 + │   │   │   │   │   ├── length 432 + │   │   │   │   │   └── watermark 433 + │   │   │   │   ├── dev 434 + │   │   │   │   ├── in_anglvel_hysteresis 435 + │   │   │   │   ├── in_anglvel_offset 436 + │   │   │   │   ├── in_anglvel_sampling_frequency 437 + │   │   │   │   ├── in_anglvel_scale 438 + │   │   │   │   ├── in_anglvel_x_raw 439 + │   │   │   │   ├── in_anglvel_y_raw 440 + │   │   │   │   ├── in_anglvel_z_raw 441 + │   │   │   │   ├── name 442 + │   │   │   │   ├── scan_elements 443 + │   │   │   │   │   ├── in_anglvel_x_en 444 + │   │   │   │   │   ├── in_anglvel_x_index 445 + │   │   │   │   │   ├── in_anglvel_x_type 446 + │   │   │   │   │   ├── in_anglvel_y_en 447 + │   │   │   │   │   ├── in_anglvel_y_index 448 + │   │   │   │   │   ├── in_anglvel_y_type 449 + │   │   │   │   │   ├── in_anglvel_z_en 450 + │   │   │   │   │   ├── in_anglvel_z_index 451 + │   │   │   │   │   └── in_anglvel_z_type 452 + │   │   │   │   ├── trigger 453 + │   │   │   │   │   └── current_trigger 454 + ...
+7
MAINTAINERS
··· 6205 6205 S: Supported 6206 6206 F: drivers/idle/intel_idle.c 6207 6207 6208 + INTEL INTEGRATED SENSOR HUB DRIVER 6209 + M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> 6210 + M: Jiri Kosina <jikos@kernel.org> 6211 + L: linux-input@vger.kernel.org 6212 + S: Maintained 6213 + F: drivers/hid/intel-ish-hid/ 6214 + 6208 6215 INTEL PSTATE DRIVER 6209 6216 M: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> 6210 6217 M: Len Brown <lenb@kernel.org>
+17 -9
drivers/hid/Kconfig
··· 457 457 - Logitech WingMan Cordless RumblePad 458 458 - Logitech WingMan Cordless RumblePad 2 459 459 - Logitech WingMan Force 3D 460 - - Logitech Formula Force EX 461 - - Logitech WingMan Formula Force GP 462 460 463 461 and if you want to enable force feedback for them. 464 462 Note: if you say N here, this device will still be supported, but without ··· 486 488 select INPUT_FF_MEMLESS 487 489 default LOGITECH_FF 488 490 help 489 - Say Y here if you want to enable force feedback and range setting 491 + Say Y here if you want to enable force feedback and range setting(*) 490 492 support for following Logitech wheels: 493 + - Logitech G25 (*) 494 + - Logitech G27 (*) 495 + - Logitech G29 (*) 491 496 - Logitech Driving Force 492 - - Logitech Driving Force Pro 493 - - Logitech Driving Force GT 494 - - Logitech G25 495 - - Logitech G27 496 - - Logitech MOMO/MOMO 2 497 - - Logitech Formula Force EX 497 + - Logitech Driving Force Pro (*) 498 + - Logitech Driving Force GT (*) 499 + - Logitech Driving Force EX/RX 500 + - Logitech Driving Force Wireless 501 + - Logitech Speed Force Wireless 502 + - Logitech MOMO Force 503 + - Logitech MOMO Racing Force 504 + - Logitech Formula Force GP 505 + - Logitech Formula Force EX/RX 506 + - Logitech Wingman Formula Force GP 498 507 499 508 config HID_MAGICMOUSE 500 509 tristate "Apple Magic Mouse/Trackpad multi-touch support" ··· 867 862 select POWER_SUPPLY 868 863 select NEW_LEDS 869 864 select LEDS_CLASS 865 + select LEDS_TRIGGERS 870 866 help 871 867 Say Y here if you want to use the USB or BT version of the Wacom Intuos 872 868 or Graphire tablet. ··· 972 966 source "drivers/hid/usbhid/Kconfig" 973 967 974 968 source "drivers/hid/i2c-hid/Kconfig" 969 + 970 + source "drivers/hid/intel-ish-hid/Kconfig" 975 971 976 972 endmenu
+2
drivers/hid/Makefile
··· 113 113 obj-$(CONFIG_USB_KBD) += usbhid/ 114 114 115 115 obj-$(CONFIG_I2C_HID) += i2c-hid/ 116 + 117 + obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-hid/
+14 -12
drivers/hid/hid-alps.c
··· 139 139 if (read_flag) { 140 140 readbuf = kzalloc(U1_FEATURE_REPORT_LEN, GFP_KERNEL); 141 141 if (!readbuf) { 142 - kfree(input); 143 - return -ENOMEM; 142 + ret = -ENOMEM; 143 + goto exit; 144 144 } 145 145 146 146 ret = hid_hw_raw_request(hdev, U1_FEATURE_REPORT_ID, readbuf, ··· 149 149 150 150 if (ret < 0) { 151 151 dev_err(&hdev->dev, "failed read register (%d)\n", ret); 152 + kfree(readbuf); 152 153 goto exit; 153 154 } 154 155 ··· 191 190 if (z != 0) { 192 191 input_mt_report_slot_state(hdata->input, 193 192 MT_TOOL_FINGER, 1); 193 + input_report_abs(hdata->input, 194 + ABS_MT_POSITION_X, x); 195 + input_report_abs(hdata->input, 196 + ABS_MT_POSITION_Y, y); 197 + input_report_abs(hdata->input, 198 + ABS_MT_PRESSURE, z); 194 199 } else { 195 200 input_mt_report_slot_state(hdata->input, 196 201 MT_TOOL_FINGER, 0); 197 - break; 198 202 } 199 - 200 - input_report_abs(hdata->input, ABS_MT_POSITION_X, x); 201 - input_report_abs(hdata->input, ABS_MT_POSITION_Y, y); 202 - input_report_abs(hdata->input, ABS_MT_PRESSURE, z); 203 - 204 203 } 205 204 206 205 input_mt_sync_frame(hdata->input); ··· 245 244 static int alps_post_reset(struct hid_device *hdev) 246 245 { 247 246 return u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1, 248 - NULL, U1_TP_ABS_MODE, false); 247 + NULL, U1_TP_ABS_MODE | U1_SP_ABS_MODE, false); 249 248 } 250 249 251 250 static int alps_post_resume(struct hid_device *hdev) 252 251 { 253 252 return u1_read_write_register(hdev, ADDRESS_U1_DEV_CTRL_1, 254 - NULL, U1_TP_ABS_MODE, false); 253 + NULL, U1_TP_ABS_MODE | U1_SP_ABS_MODE, false); 255 254 } 256 255 #endif /* CONFIG_PM */ 257 256 ··· 384 383 385 384 input2 = input_allocate_device(); 386 385 if (!input2) { 387 - input_free_device(input2); 386 + ret = -ENOMEM; 388 387 goto exit; 389 388 } 390 389 ··· 426 425 __set_bit(INPUT_PROP_POINTER, input2->propbit); 427 426 __set_bit(INPUT_PROP_POINTING_STICK, input2->propbit); 428 427 429 - if (input_register_device(data->input2)) { 428 + ret = input_register_device(data->input2); 429 + if (ret) { 430 430 input_free_device(input2); 431 431 goto exit; 432 432 }
+10 -2
drivers/hid/hid-core.c
··· 727 727 (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 || 728 728 hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 || 729 729 hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP || 730 + hid->product == USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP || 730 731 hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || 731 732 hid->product == USB_DEVICE_ID_MS_POWER_COVER) && 732 733 hid->group == HID_GROUP_MULTITOUCH) ··· 1917 1916 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, 1918 1917 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_I405X) }, 1919 1918 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, 1920 - { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) }, 1919 + { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) }, 1921 1920 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) }, 1922 1921 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912) }, 1923 1922 { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, ··· 1983 1982 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3) }, 1984 1983 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2) }, 1985 1984 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP) }, 1985 + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP) }, 1986 1986 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, 1987 1987 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K) }, 1988 1988 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600) }, ··· 2039 2037 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, 2040 2038 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7_OLD) }, 2041 2039 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, 2040 + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9) }, 2042 2041 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, 2043 2042 { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT5) }, 2044 2043 { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, ··· 2086 2083 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, 2087 2084 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850) }, 2088 2085 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, 2086 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, 2087 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, 2088 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, 2089 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, 2090 + { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, 2089 2091 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, 2090 2092 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SUPER_JOY_BOX_3) }, 2091 2093 { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD) }, ··· 2488 2480 { HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) }, 2489 2481 { HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) }, 2490 2482 { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) }, 2491 - #if defined(CONFIG_MOUSE_SYNAPTICS_USB) || defined(CONFIG_MOUSE_SYNAPTICS_USB_MODULE) 2483 + #if IS_ENABLED(CONFIG_MOUSE_SYNAPTICS_USB) 2492 2484 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP) }, 2493 2485 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_INT_TP) }, 2494 2486 { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_CPAD) },
+11 -1
drivers/hid/hid-ids.h
··· 268 268 #define USB_DEVICE_ID_CORSAIR_K95RGB 0x1b11 269 269 #define USB_DEVICE_ID_CORSAIR_M65RGB 0x1b12 270 270 #define USB_DEVICE_ID_CORSAIR_K70RGB 0x1b13 271 + #define USB_DEVICE_ID_CORSAIR_STRAFE 0x1b15 271 272 #define USB_DEVICE_ID_CORSAIR_K65RGB 0x1b17 272 273 273 274 #define USB_VENDOR_ID_CREATIVELABS 0x041e ··· 566 565 #define USB_DEVICE_ID_KYE_GPEN_560 0x5003 567 566 #define USB_DEVICE_ID_KYE_EASYPEN_I405X 0x5010 568 567 #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X 0x5011 569 - #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2 0x501a 568 + #define USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2 0x501a 570 569 #define USB_DEVICE_ID_KYE_EASYPEN_M610X 0x5013 571 570 #define USB_DEVICE_ID_KYE_PENSKETCH_M912 0x5015 572 571 ··· 714 713 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3 0x07dc 715 714 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2 0x07e2 716 715 #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP 0x07dd 716 + #define USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP 0x07e9 717 717 #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07de 718 718 #define USB_DEVICE_ID_MS_POWER_COVER 0x07da 719 719 ··· 861 859 #define USB_DEVICE_ID_SAITEK_PS1000 0x0621 862 860 #define USB_DEVICE_ID_SAITEK_RAT7_OLD 0x0ccb 863 861 #define USB_DEVICE_ID_SAITEK_RAT7 0x0cd7 862 + #define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa 864 863 #define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0 865 864 866 865 #define USB_VENDOR_ID_SAMSUNG 0x0419 ··· 999 996 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 1000 997 #define USB_DEVICE_ID_UCLOGIC_WIRELESS_TABLET_TWHL850 0x0522 1001 998 #define USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60 0x0781 999 + #define USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3 0x3031 1000 + #define USB_DEVICE_ID_UGEE_TABLET_81 0x0081 1001 + #define USB_DEVICE_ID_UGEE_TABLET_45 0x0045 1002 + #define USB_DEVICE_ID_YIYNOVA_TABLET 0x004d 1002 1003 1003 1004 #define USB_VENDOR_ID_UNITEC 0x227d 1004 1005 #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 ··· 1091 1084 #define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b 1092 1085 #define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 1093 1086 #define USB_DEVICE_ID_RAPHNET_4NES4SNES 0x0003 1087 + 1088 + #define USB_VENDOR_ID_UGTIZER 0x2179 1089 + #define USB_DEVICE_ID_UGTIZER_TABLET_GP0610 0x0053 1094 1090 1095 1091 #endif
+10
drivers/hid/hid-input.c
··· 604 604 break; 605 605 } 606 606 607 + /* 608 + * Some lazy vendors declare 255 usages for System Control, 609 + * leading to the creation of ABS_X|Y axis and too many others. 610 + * It wouldn't be a problem if joydev doesn't consider the 611 + * device as a joystick then. 612 + */ 613 + if (field->application == HID_GD_SYSTEM_CONTROL) 614 + goto ignore; 615 + 607 616 if ((usage->hid & 0xf0) == 0x90) { /* D-pad */ 608 617 switch (usage->hid) { 609 618 case HID_GD_UP: usage->hat_dir = 1; break; ··· 962 953 case HID_UP_HPVENDOR2: 963 954 set_bit(EV_REP, input->evbit); 964 955 switch (usage->hid & HID_USAGE) { 956 + case 0x001: map_key_clear(KEY_MICMUTE); break; 965 957 case 0x003: map_key_clear(KEY_BRIGHTNESSDOWN); break; 966 958 case 0x004: map_key_clear(KEY_BRIGHTNESSUP); break; 967 959 default: goto ignore;
+106 -17
drivers/hid/hid-kye.c
··· 19 19 20 20 #include "hid-ids.h" 21 21 22 - /* 23 - * See EasyPen i405X description, device and HID report descriptors at 24 - * http://sf.net/apps/mediawiki/digimend/?title=KYE_EasyPen_i405X 25 - */ 26 - 27 22 /* Original EasyPen i405X report descriptor size */ 28 23 #define EASYPEN_I405X_RDESC_ORIG_SIZE 476 29 24 ··· 76 81 0xC0, /* End Collection, */ 77 82 0xC0 /* End Collection */ 78 83 }; 79 - 80 - /* 81 - * See MousePen i608X description, device and HID report descriptors at 82 - * http://sf.net/apps/mediawiki/digimend/?title=KYE_MousePen_i608X 83 - */ 84 84 85 85 /* Original MousePen i608X report descriptor size */ 86 86 #define MOUSEPEN_I608X_RDESC_ORIG_SIZE 476 ··· 176 186 0xC0 /* End Collection */ 177 187 }; 178 188 179 - /* 180 - * See EasyPen M610X description, device and HID report descriptors at 181 - * http://sf.net/apps/mediawiki/digimend/?title=KYE_EasyPen_M610X 182 - */ 189 + /* Original MousePen i608X v2 report descriptor size */ 190 + #define MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE 482 191 + 192 + /* Fixed MousePen i608X v2 report descriptor */ 193 + static __u8 mousepen_i608x_v2_rdesc_fixed[] = { 194 + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 195 + 0x09, 0x01, /* Usage (01h), */ 196 + 0xA1, 0x01, /* Collection (Application), */ 197 + 0x85, 0x05, /* Report ID (5), */ 198 + 0x09, 0x01, /* Usage (01h), */ 199 + 0x15, 0x80, /* Logical Minimum (-128), */ 200 + 0x25, 0x7F, /* Logical Maximum (127), */ 201 + 0x75, 0x08, /* Report Size (8), */ 202 + 0x95, 0x07, /* Report Count (7), */ 203 + 0xB1, 0x02, /* Feature (Variable), */ 204 + 0xC0, /* End Collection, */ 205 + 0x05, 0x0D, /* Usage Page (Digitizer), */ 206 + 0x09, 0x02, /* Usage (Pen), */ 207 + 0xA1, 0x01, /* Collection (Application), */ 208 + 0x85, 0x10, /* Report ID (16), */ 209 + 0x09, 0x20, /* Usage (Stylus), */ 210 + 0xA0, /* Collection (Physical), */ 211 + 0x14, /* Logical Minimum (0), */ 212 + 0x25, 0x01, /* Logical Maximum (1), */ 213 + 0x75, 0x01, /* Report Size (1), */ 214 + 0x09, 0x42, /* Usage (Tip Switch), */ 215 + 0x09, 0x44, /* Usage (Barrel Switch), */ 216 + 0x09, 0x46, /* Usage (Tablet Pick), */ 217 + 0x95, 0x03, /* Report Count (3), */ 218 + 0x81, 0x02, /* Input (Variable), */ 219 + 0x95, 0x04, /* Report Count (4), */ 220 + 0x81, 0x03, /* Input (Constant, Variable), */ 221 + 0x09, 0x32, /* Usage (In Range), */ 222 + 0x95, 0x01, /* Report Count (1), */ 223 + 0x81, 0x02, /* Input (Variable), */ 224 + 0x75, 0x10, /* Report Size (16), */ 225 + 0x95, 0x01, /* Report Count (1), */ 226 + 0xA4, /* Push, */ 227 + 0x05, 0x01, /* Usage Page (Desktop), */ 228 + 0x55, 0xFD, /* Unit Exponent (-3), */ 229 + 0x65, 0x13, /* Unit (Inch), */ 230 + 0x34, /* Physical Minimum (0), */ 231 + 0x09, 0x30, /* Usage (X), */ 232 + 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 233 + 0x27, 0x00, 0xA0, 0x00, 0x00, /* Logical Maximum (40960), */ 234 + 0x81, 0x02, /* Input (Variable), */ 235 + 0x09, 0x31, /* Usage (Y), */ 236 + 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 237 + 0x26, 0x00, 0x78, /* Logical Maximum (30720), */ 238 + 0x81, 0x02, /* Input (Variable), */ 239 + 0xB4, /* Pop, */ 240 + 0x09, 0x30, /* Usage (Tip Pressure), */ 241 + 0x26, 0xFF, 0x07, /* Logical Maximum (2047), */ 242 + 0x81, 0x02, /* Input (Variable), */ 243 + 0xC0, /* End Collection, */ 244 + 0xC0, /* End Collection, */ 245 + 0x05, 0x01, /* Usage Page (Desktop), */ 246 + 0x09, 0x02, /* Usage (Mouse), */ 247 + 0xA1, 0x01, /* Collection (Application), */ 248 + 0x85, 0x11, /* Report ID (17), */ 249 + 0x09, 0x01, /* Usage (Pointer), */ 250 + 0xA0, /* Collection (Physical), */ 251 + 0x14, /* Logical Minimum (0), */ 252 + 0xA4, /* Push, */ 253 + 0x05, 0x09, /* Usage Page (Button), */ 254 + 0x75, 0x01, /* Report Size (1), */ 255 + 0x19, 0x01, /* Usage Minimum (01h), */ 256 + 0x29, 0x03, /* Usage Maximum (03h), */ 257 + 0x25, 0x01, /* Logical Maximum (1), */ 258 + 0x95, 0x03, /* Report Count (3), */ 259 + 0x81, 0x02, /* Input (Variable), */ 260 + 0x95, 0x05, /* Report Count (5), */ 261 + 0x81, 0x01, /* Input (Constant), */ 262 + 0xB4, /* Pop, */ 263 + 0x95, 0x01, /* Report Count (1), */ 264 + 0xA4, /* Push, */ 265 + 0x55, 0xFD, /* Unit Exponent (-3), */ 266 + 0x65, 0x13, /* Unit (Inch), */ 267 + 0x34, /* Physical Minimum (0), */ 268 + 0x75, 0x10, /* Report Size (16), */ 269 + 0x09, 0x30, /* Usage (X), */ 270 + 0x46, 0x40, 0x1F, /* Physical Maximum (8000), */ 271 + 0x27, 0x00, 0xA0, 0x00, 0x00, /* Logical Maximum (40960), */ 272 + 0x81, 0x02, /* Input (Variable), */ 273 + 0x09, 0x31, /* Usage (Y), */ 274 + 0x46, 0x70, 0x17, /* Physical Maximum (6000), */ 275 + 0x26, 0x00, 0x78, /* Logical Maximum (30720), */ 276 + 0x81, 0x02, /* Input (Variable), */ 277 + 0xB4, /* Pop, */ 278 + 0x75, 0x08, /* Report Size (8), */ 279 + 0x09, 0x38, /* Usage (Wheel), */ 280 + 0x15, 0xFF, /* Logical Minimum (-1), */ 281 + 0x25, 0x01, /* Logical Maximum (1), */ 282 + 0x81, 0x06, /* Input (Variable, Relative), */ 283 + 0x81, 0x01, /* Input (Constant), */ 284 + 0xC0, /* End Collection, */ 285 + 0xC0 /* End Collection */ 286 + }; 183 287 184 288 /* Original EasyPen M610X report descriptor size */ 185 289 #define EASYPEN_M610X_RDESC_ORIG_SIZE 476 ··· 538 454 } 539 455 break; 540 456 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: 541 - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2: 542 457 if (*rsize == MOUSEPEN_I608X_RDESC_ORIG_SIZE) { 543 458 rdesc = mousepen_i608x_rdesc_fixed; 544 459 *rsize = sizeof(mousepen_i608x_rdesc_fixed); 460 + } 461 + break; 462 + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2: 463 + if (*rsize == MOUSEPEN_I608X_V2_RDESC_ORIG_SIZE) { 464 + rdesc = mousepen_i608x_v2_rdesc_fixed; 465 + *rsize = sizeof(mousepen_i608x_v2_rdesc_fixed); 545 466 } 546 467 break; 547 468 case USB_DEVICE_ID_KYE_EASYPEN_M610X: ··· 642 553 switch (id->product) { 643 554 case USB_DEVICE_ID_KYE_EASYPEN_I405X: 644 555 case USB_DEVICE_ID_KYE_MOUSEPEN_I608X: 645 - case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2: 556 + case USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2: 646 557 case USB_DEVICE_ID_KYE_EASYPEN_M610X: 647 558 case USB_DEVICE_ID_KYE_PENSKETCH_M912: 648 559 ret = kye_tablet_enable(hdev); ··· 675 586 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 676 587 USB_DEVICE_ID_KYE_MOUSEPEN_I608X) }, 677 588 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 678 - USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2) }, 589 + USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2) }, 679 590 { HID_USB_DEVICE(USB_VENDOR_ID_KYE, 680 591 USB_DEVICE_ID_KYE_EASYPEN_M610X) }, 681 592 { HID_USB_DEVICE(USB_VENDOR_ID_KYE,
+71 -15
drivers/hid/hid-lg.c
··· 49 49 #define FV_RDESC_ORIG_SIZE 130 50 50 #define MOMO_RDESC_ORIG_SIZE 87 51 51 #define MOMO2_RDESC_ORIG_SIZE 87 52 + #define FFG_RDESC_ORIG_SIZE 85 52 53 53 54 /* Fixed report descriptors for Logitech Driving Force (and Pro) 54 55 * wheel controllers ··· 335 334 0xC0 /* End Collection */ 336 335 }; 337 336 337 + static __u8 ffg_rdesc_fixed[] = { 338 + 0x05, 0x01, /* Usage Page (Desktop), */ 339 + 0x09, 0x04, /* Usage (Joystik), */ 340 + 0xA1, 0x01, /* Collection (Application), */ 341 + 0xA1, 0x02, /* Collection (Logical), */ 342 + 0x95, 0x01, /* Report Count (1), */ 343 + 0x75, 0x0A, /* Report Size (10), */ 344 + 0x15, 0x00, /* Logical Minimum (0), */ 345 + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ 346 + 0x35, 0x00, /* Physical Minimum (0), */ 347 + 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ 348 + 0x09, 0x30, /* Usage (X), */ 349 + 0x81, 0x02, /* Input (Variable), */ 350 + 0x95, 0x06, /* Report Count (6), */ 351 + 0x75, 0x01, /* Report Size (1), */ 352 + 0x25, 0x01, /* Logical Maximum (1), */ 353 + 0x45, 0x01, /* Physical Maximum (1), */ 354 + 0x05, 0x09, /* Usage Page (Button), */ 355 + 0x19, 0x01, /* Usage Minimum (01h), */ 356 + 0x29, 0x06, /* Usage Maximum (06h), */ 357 + 0x81, 0x02, /* Input (Variable), */ 358 + 0x95, 0x01, /* Report Count (1), */ 359 + 0x75, 0x08, /* Report Size (8), */ 360 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 361 + 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 362 + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 363 + 0x09, 0x01, /* Usage (01h), */ 364 + 0x81, 0x02, /* Input (Variable), */ 365 + 0x05, 0x01, /* Usage Page (Desktop), */ 366 + 0x81, 0x01, /* Input (Constant), */ 367 + 0x09, 0x31, /* Usage (Y), */ 368 + 0x81, 0x02, /* Input (Variable), */ 369 + 0x09, 0x32, /* Usage (Z), */ 370 + 0x81, 0x02, /* Input (Variable), */ 371 + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ 372 + 0x09, 0x01, /* Usage (01h), */ 373 + 0x81, 0x02, /* Input (Variable), */ 374 + 0xC0, /* End Collection, */ 375 + 0xA1, 0x02, /* Collection (Logical), */ 376 + 0x09, 0x02, /* Usage (02h), */ 377 + 0x95, 0x07, /* Report Count (7), */ 378 + 0x91, 0x02, /* Output (Variable), */ 379 + 0xC0, /* End Collection, */ 380 + 0xC0 /* End Collection */ 381 + }; 382 + 338 383 /* 339 384 * Certain Logitech keyboards send in report #3 keys which are far 340 385 * above the logical maximum described in descriptor. This extends ··· 390 343 unsigned int *rsize) 391 344 { 392 345 struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 393 - struct usb_device_descriptor *udesc; 394 - __u16 bcdDevice, rev_maj, rev_min; 395 346 396 347 if ((drv_data->quirks & LG_RDESC) && *rsize >= 91 && rdesc[83] == 0x26 && 397 348 rdesc[84] == 0x8c && rdesc[85] == 0x02) { ··· 408 363 409 364 switch (hdev->product) { 410 365 366 + case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG: 367 + if (*rsize == FFG_RDESC_ORIG_SIZE) { 368 + hid_info(hdev, 369 + "fixing up Logitech Wingman Formula Force GP report descriptor\n"); 370 + rdesc = ffg_rdesc_fixed; 371 + *rsize = sizeof(ffg_rdesc_fixed); 372 + } 373 + break; 374 + 411 375 /* Several wheels report as this id when operating in emulation mode. */ 412 376 case USB_DEVICE_ID_LOGITECH_WHEEL: 413 - udesc = &(hid_to_usb_dev(hdev)->descriptor); 414 - if (!udesc) { 415 - hid_err(hdev, "NULL USB device descriptor\n"); 416 - break; 417 - } 418 - bcdDevice = le16_to_cpu(udesc->bcdDevice); 419 - rev_maj = bcdDevice >> 8; 420 - rev_min = bcdDevice & 0xff; 421 - 422 - /* Update the report descriptor for only the Driving Force wheel */ 423 - if (rev_maj == 1 && rev_min == 2 && 424 - *rsize == DF_RDESC_ORIG_SIZE) { 377 + if (*rsize == DF_RDESC_ORIG_SIZE) { 425 378 hid_info(hdev, 426 379 "fixing up Logitech Driving Force report descriptor\n"); 427 380 rdesc = df_rdesc_fixed; ··· 664 621 usage->code == ABS_RZ)) { 665 622 switch (hdev->product) { 666 623 case USB_DEVICE_ID_LOGITECH_G29_WHEEL: 624 + case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG: 667 625 case USB_DEVICE_ID_LOGITECH_WHEEL: 668 626 case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: 669 627 case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: ··· 697 653 if (drv_data->quirks & LG_FF4) { 698 654 return lg4ff_adjust_input_event(hdev, field, usage, value, drv_data); 699 655 } 656 + 657 + return 0; 658 + } 659 + 660 + static int lg_raw_event(struct hid_device *hdev, struct hid_report *report, 661 + u8 *rd, int size) 662 + { 663 + struct lg_drv_data *drv_data = hid_get_drvdata(hdev); 664 + 665 + if (drv_data->quirks & LG_FF4) 666 + return lg4ff_raw_event(hdev, report, rd, size, drv_data); 700 667 701 668 return 0; 702 669 } ··· 864 809 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), 865 810 .driver_data = LG_FF4 }, 866 811 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG), 867 - .driver_data = LG_FF }, 812 + .driver_data = LG_NOGET | LG_FF4 }, 868 813 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2), 869 814 .driver_data = LG_FF2 }, 870 815 { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940), ··· 885 830 .input_mapping = lg_input_mapping, 886 831 .input_mapped = lg_input_mapped, 887 832 .event = lg_event, 833 + .raw_event = lg_raw_event, 888 834 .probe = lg_probe, 889 835 .remove = lg_remove, 890 836 };
+109
drivers/hid/hid-lg4ff.c
··· 75 75 76 76 struct lg4ff_wheel_data { 77 77 const u32 product_id; 78 + u16 combine; 78 79 u16 range; 79 80 const u16 min_range; 80 81 const u16 max_range; ··· 137 136 }; 138 137 139 138 static const struct lg4ff_wheel lg4ff_devices[] = { 139 + {USB_DEVICE_ID_LOGITECH_WINGMAN_FFG, lg4ff_wheel_effects, 40, 180, NULL}, 140 140 {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, 141 141 {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, 142 142 {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_dfp}, ··· 330 328 } 331 329 } 332 330 331 + int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report, 332 + u8 *rd, int size, struct lg_drv_data *drv_data) 333 + { 334 + int offset; 335 + struct lg4ff_device_entry *entry = drv_data->device_props; 336 + 337 + if (!entry) 338 + return 0; 339 + 340 + /* adjust HID report present combined pedals data */ 341 + if (entry->wdata.combine) { 342 + switch (entry->wdata.product_id) { 343 + case USB_DEVICE_ID_LOGITECH_WHEEL: 344 + rd[5] = rd[3]; 345 + rd[6] = 0x7F; 346 + return 1; 347 + case USB_DEVICE_ID_LOGITECH_WINGMAN_FFG: 348 + case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: 349 + case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: 350 + rd[4] = rd[3]; 351 + rd[5] = 0x7F; 352 + return 1; 353 + case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: 354 + rd[5] = rd[4]; 355 + rd[6] = 0x7F; 356 + return 1; 357 + case USB_DEVICE_ID_LOGITECH_G25_WHEEL: 358 + case USB_DEVICE_ID_LOGITECH_G27_WHEEL: 359 + offset = 5; 360 + break; 361 + case USB_DEVICE_ID_LOGITECH_DFGT_WHEEL: 362 + case USB_DEVICE_ID_LOGITECH_G29_WHEEL: 363 + offset = 6; 364 + break; 365 + case USB_DEVICE_ID_LOGITECH_WII_WHEEL: 366 + offset = 3; 367 + break; 368 + default: 369 + return 0; 370 + } 371 + 372 + /* Compute a combined axis when wheel does not supply it */ 373 + rd[offset] = (0xFF + rd[offset] - rd[offset+1]) >> 1; 374 + rd[offset+1] = 0x7F; 375 + return 1; 376 + } 377 + 378 + return 0; 379 + } 380 + 333 381 static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const struct lg4ff_wheel *wheel, 334 382 const struct lg4ff_multimode_wheel *mmode_wheel, 335 383 const u16 real_product_id) ··· 397 345 { 398 346 struct lg4ff_wheel_data t_wdata = { .product_id = wheel->product_id, 399 347 .real_product_id = real_product_id, 348 + .combine = 0, 400 349 .min_range = wheel->min_range, 401 350 .max_range = wheel->max_range, 402 351 .set_range = wheel->set_range, ··· 938 885 } 939 886 static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store); 940 887 888 + static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute *attr, 889 + char *buf) 890 + { 891 + struct hid_device *hid = to_hid_device(dev); 892 + struct lg4ff_device_entry *entry; 893 + struct lg_drv_data *drv_data; 894 + size_t count; 895 + 896 + drv_data = hid_get_drvdata(hid); 897 + if (!drv_data) { 898 + hid_err(hid, "Private driver data not found!\n"); 899 + return 0; 900 + } 901 + 902 + entry = drv_data->device_props; 903 + if (!entry) { 904 + hid_err(hid, "Device properties not found!\n"); 905 + return 0; 906 + } 907 + 908 + count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine); 909 + return count; 910 + } 911 + 912 + static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute *attr, 913 + const char *buf, size_t count) 914 + { 915 + struct hid_device *hid = to_hid_device(dev); 916 + struct lg4ff_device_entry *entry; 917 + struct lg_drv_data *drv_data; 918 + u16 combine = simple_strtoul(buf, NULL, 10); 919 + 920 + drv_data = hid_get_drvdata(hid); 921 + if (!drv_data) { 922 + hid_err(hid, "Private driver data not found!\n"); 923 + return -EINVAL; 924 + } 925 + 926 + entry = drv_data->device_props; 927 + if (!entry) { 928 + hid_err(hid, "Device properties not found!\n"); 929 + return -EINVAL; 930 + } 931 + 932 + if (combine > 1) 933 + combine = 1; 934 + 935 + entry->wdata.combine = combine; 936 + return count; 937 + } 938 + static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_combine_show, lg4ff_combine_store); 939 + 941 940 /* Export the currently set range of the wheel */ 942 941 static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, 943 942 char *buf) ··· 1364 1259 } 1365 1260 1366 1261 /* Create sysfs interface */ 1262 + error = device_create_file(&hid->dev, &dev_attr_combine_pedals); 1263 + if (error) 1264 + hid_warn(hid, "Unable to create sysfs interface for \"combine\", errno %d\n", error); 1367 1265 error = device_create_file(&hid->dev, &dev_attr_range); 1368 1266 if (error) 1369 1267 hid_warn(hid, "Unable to create sysfs interface for \"range\", errno %d\n", error); ··· 1466 1358 device_remove_file(&hid->dev, &dev_attr_alternate_modes); 1467 1359 } 1468 1360 1361 + device_remove_file(&hid->dev, &dev_attr_combine_pedals); 1469 1362 device_remove_file(&hid->dev, &dev_attr_range); 1470 1363 #ifdef CONFIG_LEDS_CLASS 1471 1364 {
+4
drivers/hid/hid-lg4ff.h
··· 6 6 7 7 int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, 8 8 struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data); 9 + int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report, 10 + u8 *rd, int size, struct lg_drv_data *drv_data); 9 11 int lg4ff_init(struct hid_device *hdev); 10 12 int lg4ff_deinit(struct hid_device *hdev); 11 13 #else 12 14 static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, 13 15 struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data) { return 0; } 16 + static inline int lg4ff_raw_event(struct hid_device *hdev, struct hid_report *report, 17 + u8 *rd, int size, struct lg_drv_data *drv_data) { return 0; } 14 18 static inline int lg4ff_init(struct hid_device *hdev) { return -1; } 15 19 static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; } 16 20 #endif
+3 -9
drivers/hid/hid-microsoft.c
··· 28 28 #define MS_RDESC 0x08 29 29 #define MS_NOGET 0x10 30 30 #define MS_DUPLICATE_USAGES 0x20 31 - #define MS_RDESC_3K 0x40 32 31 33 32 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, 34 33 unsigned int *rsize) ··· 43 44 hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); 44 45 rdesc[557] = 0x35; 45 46 rdesc[559] = 0x45; 46 - } 47 - /* the same as above (s/usage/physical/) */ 48 - if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 && 49 - rdesc[95] == 0x00 && rdesc[96] == 0x29 && 50 - rdesc[97] == 0xff) { 51 - rdesc[94] = 0x35; 52 - rdesc[96] = 0x45; 53 47 } 54 48 return rdesc; 55 49 } ··· 263 271 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), 264 272 .driver_data = MS_PRESENTER }, 265 273 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), 266 - .driver_data = MS_ERGONOMY | MS_RDESC_3K }, 274 + .driver_data = MS_ERGONOMY }, 267 275 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_7K), 268 276 .driver_data = MS_ERGONOMY }, 269 277 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_600), ··· 279 287 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2), 280 288 .driver_data = MS_HIDINPUT }, 281 289 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP), 290 + .driver_data = MS_HIDINPUT }, 291 + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP), 282 292 .driver_data = MS_HIDINPUT }, 283 293 { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), 284 294 .driver_data = MS_HIDINPUT },
+2
drivers/hid/hid-saitek.c
··· 183 183 .driver_data = SAITEK_RELEASE_MODE_RAT7 }, 184 184 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), 185 185 .driver_data = SAITEK_RELEASE_MODE_RAT7 }, 186 + { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT9), 187 + .driver_data = SAITEK_RELEASE_MODE_RAT7 }, 186 188 { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9), 187 189 .driver_data = SAITEK_RELEASE_MODE_RAT7 }, 188 190 { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7),
+4
drivers/hid/hid-sensor-hub.c
··· 16 16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 17 17 * 18 18 */ 19 + 19 20 #include <linux/device.h> 20 21 #include <linux/hid.h> 21 22 #include <linux/module.h> ··· 798 797 .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, 799 798 { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_ITE, 800 799 USB_DEVICE_ID_ITE_LENOVO_YOGA900), 800 + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, 801 + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_0, 802 + 0x22D8), 801 803 .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, 802 804 { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, HID_ANY_ID, 803 805 HID_ANY_ID) },
+74 -14
drivers/hid/hid-sony.c
··· 8 8 * Copyright (c) 2012 David Dillow <dave@thedillows.org> 9 9 * Copyright (c) 2006-2013 Jiri Kosina 10 10 * Copyright (c) 2013 Colin Leitner <colin.leitner@gmail.com> 11 - * Copyright (c) 2014 Frank Praznik <frank.praznik@gmail.com> 11 + * Copyright (c) 2014-2016 Frank Praznik <frank.praznik@gmail.com> 12 12 */ 13 13 14 14 /* ··· 51 51 #define NAVIGATION_CONTROLLER_USB BIT(9) 52 52 #define NAVIGATION_CONTROLLER_BT BIT(10) 53 53 #define SINO_LITE_CONTROLLER BIT(11) 54 + #define FUTUREMAX_DANCE_MAT BIT(12) 54 55 55 56 #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) 56 57 #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) ··· 66 65 MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) 67 66 #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ 68 67 MOTION_CONTROLLER) 68 + #define SONY_BT_DEVICE (SIXAXIS_CONTROLLER_BT | DUALSHOCK4_CONTROLLER_BT |\ 69 + MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER_BT) 69 70 70 71 #define MAX_LEDS 4 71 72 ··· 1051 1048 1052 1049 u8 mac_address[6]; 1053 1050 u8 worker_initialized; 1051 + u8 defer_initialization; 1054 1052 u8 cable_state; 1055 1053 u8 battery_charging; 1056 1054 u8 battery_capacity; ··· 1061 1057 u8 led_delay_off[MAX_LEDS]; 1062 1058 u8 led_count; 1063 1059 }; 1060 + 1061 + static inline void sony_schedule_work(struct sony_sc *sc) 1062 + { 1063 + if (!sc->defer_initialization) 1064 + schedule_work(&sc->state_worker); 1065 + } 1064 1066 1065 1067 static u8 *sixaxis_fixup(struct hid_device *hdev, u8 *rdesc, 1066 1068 unsigned int *rsize) ··· 1135 1125 { 1136 1126 struct sony_sc *sc = hid_get_drvdata(hdev); 1137 1127 1138 - if (sc->quirks & SINO_LITE_CONTROLLER) 1128 + if (sc->quirks & (SINO_LITE_CONTROLLER | FUTUREMAX_DANCE_MAT)) 1139 1129 return rdesc; 1140 1130 1141 1131 /* ··· 1325 1315 size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) 1326 1316 && rd[0] == 0x11 && size == 78)) { 1327 1317 dualshock4_parse_report(sc, rd, size); 1318 + } 1319 + 1320 + if (sc->defer_initialization) { 1321 + sc->defer_initialization = 0; 1322 + sony_schedule_work(sc); 1328 1323 } 1329 1324 1330 1325 return 0; ··· 1569 1554 static void sony_set_leds(struct sony_sc *sc) 1570 1555 { 1571 1556 if (!(sc->quirks & BUZZ_CONTROLLER)) 1572 - schedule_work(&sc->state_worker); 1557 + sony_schedule_work(sc); 1573 1558 else 1574 1559 buzz_set_leds(sc); 1575 1560 } ··· 1680 1665 new_off != drv_data->led_delay_off[n]) { 1681 1666 drv_data->led_delay_on[n] = new_on; 1682 1667 drv_data->led_delay_off[n] = new_off; 1683 - schedule_work(&drv_data->state_worker); 1668 + sony_schedule_work(drv_data); 1684 1669 } 1685 1670 1686 1671 return 0; ··· 1880 1865 u8 *buf = sc->output_report_dmabuf; 1881 1866 int offset; 1882 1867 1868 + /* 1869 + * NOTE: The buf[1] field of the Bluetooth report controls 1870 + * the Dualshock 4 reporting rate. 1871 + * 1872 + * Known values include: 1873 + * 1874 + * 0x80 - 1000hz (full speed) 1875 + * 0xA0 - 31hz 1876 + * 0xB0 - 20hz 1877 + * 0xD0 - 66hz 1878 + */ 1883 1879 if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { 1884 1880 memset(buf, 0, DS4_REPORT_0x05_SIZE); 1885 1881 buf[0] = 0x05; ··· 2002 1976 sc->left = effect->u.rumble.strong_magnitude / 256; 2003 1977 sc->right = effect->u.rumble.weak_magnitude / 256; 2004 1978 2005 - schedule_work(&sc->state_worker); 1979 + sony_schedule_work(sc); 2006 1980 return 0; 2007 1981 } 2008 1982 ··· 2065 2039 return ret; 2066 2040 } 2067 2041 2068 - static int sony_battery_probe(struct sony_sc *sc) 2042 + static int sony_battery_probe(struct sony_sc *sc, int append_dev_id) 2069 2043 { 2044 + const char *battery_str_fmt = append_dev_id ? 2045 + "sony_controller_battery_%pMR_%i" : 2046 + "sony_controller_battery_%pMR"; 2070 2047 struct power_supply_config psy_cfg = { .drv_data = sc, }; 2071 2048 struct hid_device *hdev = sc->hdev; 2072 2049 int ret; ··· 2085 2056 sc->battery_desc.get_property = sony_battery_get_property; 2086 2057 sc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY; 2087 2058 sc->battery_desc.use_for_apm = 0; 2088 - sc->battery_desc.name = kasprintf(GFP_KERNEL, 2089 - "sony_controller_battery_%pMR", 2090 - sc->mac_address); 2059 + sc->battery_desc.name = kasprintf(GFP_KERNEL, battery_str_fmt, 2060 + sc->mac_address, sc->device_id); 2091 2061 if (!sc->battery_desc.name) 2092 2062 return -ENOMEM; 2093 2063 ··· 2122 2094 * it will show up as two devices. A global list of connected controllers and 2123 2095 * their MAC addresses is maintained to ensure that a device is only connected 2124 2096 * once. 2097 + * 2098 + * Some USB-only devices masquerade as Sixaxis controllers and all have the 2099 + * same dummy Bluetooth address, so a comparison of the connection type is 2100 + * required. Devices are only rejected in the case where two devices have 2101 + * matching Bluetooth addresses on different bus types. 2125 2102 */ 2103 + static inline int sony_compare_connection_type(struct sony_sc *sc0, 2104 + struct sony_sc *sc1) 2105 + { 2106 + const int sc0_not_bt = !(sc0->quirks & SONY_BT_DEVICE); 2107 + const int sc1_not_bt = !(sc1->quirks & SONY_BT_DEVICE); 2108 + 2109 + return sc0_not_bt == sc1_not_bt; 2110 + } 2111 + 2126 2112 static int sony_check_add_dev_list(struct sony_sc *sc) 2127 2113 { 2128 2114 struct sony_sc *entry; ··· 2149 2107 ret = memcmp(sc->mac_address, entry->mac_address, 2150 2108 sizeof(sc->mac_address)); 2151 2109 if (!ret) { 2152 - ret = -EEXIST; 2153 - hid_info(sc->hdev, "controller with MAC address %pMR already connected\n", 2110 + if (sony_compare_connection_type(sc, entry)) { 2111 + ret = 1; 2112 + } else { 2113 + ret = -EEXIST; 2114 + hid_info(sc->hdev, 2115 + "controller with MAC address %pMR already connected\n", 2154 2116 sc->mac_address); 2117 + } 2155 2118 goto unlock; 2156 2119 } 2157 2120 } ··· 2332 2285 static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) 2333 2286 { 2334 2287 int ret; 2288 + int append_dev_id; 2335 2289 unsigned long quirks = id->driver_data; 2336 2290 struct sony_sc *sc; 2337 2291 unsigned int connect_mask = HID_CONNECT_DEFAULT; 2292 + 2293 + if (!strcmp(hdev->name, "FutureMax Dance Mat")) 2294 + quirks |= FUTUREMAX_DANCE_MAT; 2338 2295 2339 2296 sc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL); 2340 2297 if (sc == NULL) { ··· 2392 2341 * the Sixaxis does not want the report_id as part of the data 2393 2342 * packet, so we have to discard buf[0] when sending the actual 2394 2343 * control message, even for numbered reports, humpf! 2344 + * 2345 + * Additionally, the Sixaxis on USB isn't properly initialized 2346 + * until the PS logo button is pressed and as such won't retain 2347 + * any state set by an output report, so the initial 2348 + * configuration report is deferred until the first input 2349 + * report arrives. 2395 2350 */ 2396 2351 hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP; 2397 2352 hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; 2353 + sc->defer_initialization = 1; 2398 2354 ret = sixaxis_set_operational_usb(hdev); 2399 2355 sony_init_output_report(sc, sixaxis_send_output_report); 2400 2356 } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || ··· 2437 2379 if (ret < 0) 2438 2380 goto err_stop; 2439 2381 2440 - ret = sony_check_add(sc); 2382 + ret = append_dev_id = sony_check_add(sc); 2441 2383 if (ret < 0) 2442 2384 goto err_stop; 2443 2385 ··· 2448 2390 } 2449 2391 2450 2392 if (sc->quirks & SONY_BATTERY_SUPPORT) { 2451 - ret = sony_battery_probe(sc); 2393 + ret = sony_battery_probe(sc, append_dev_id); 2452 2394 if (ret < 0) 2453 2395 goto err_stop; 2454 2396 ··· 2544 2486 * reinitialized on resume or they won't behave properly. 2545 2487 */ 2546 2488 if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || 2547 - (sc->quirks & NAVIGATION_CONTROLLER_USB)) 2489 + (sc->quirks & NAVIGATION_CONTROLLER_USB)) { 2548 2490 sixaxis_set_operational_usb(sc->hdev); 2491 + sc->defer_initialization = 1; 2492 + } 2549 2493 2550 2494 sony_set_leds(sc); 2551 2495 }
+148 -39
drivers/hid/hid-uclogic.c
··· 21 21 22 22 #include "hid-ids.h" 23 23 24 - /* 25 - * See WPXXXXU model descriptions, device and HID report descriptors at 26 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP4030U 27 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP5540U 28 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP8060U 29 - */ 30 - 31 24 /* Size of the original descriptor of WPXXXXU tablets */ 32 25 #define WPXXXXU_RDESC_ORIG_SIZE 212 33 26 ··· 214 221 0xC0 /* End Collection */ 215 222 }; 216 223 217 - /* 218 - * See WP1062 description, device and HID report descriptors at 219 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_WP1062 220 - */ 221 - 222 224 /* Size of the original descriptor of WP1062 tablet */ 223 225 #define WP1062_RDESC_ORIG_SIZE 254 224 226 ··· 261 273 0xC0, /* End Collection, */ 262 274 0xC0 /* End Collection */ 263 275 }; 264 - 265 - /* 266 - * See PF1209 description, device and HID report descriptors at 267 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_PF1209 268 - */ 269 276 270 277 /* Size of the original descriptor of PF1209 tablet */ 271 278 #define PF1209_RDESC_ORIG_SIZE 234 ··· 338 355 0xC0, /* End Collection, */ 339 356 0xC0 /* End Collection */ 340 357 }; 341 - 342 - /* 343 - * See TWHL850 description, device and HID report descriptors at 344 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Wireless_Tablet_TWHL850 345 - */ 346 358 347 359 /* Size of the original descriptors of TWHL850 tablet */ 348 360 #define TWHL850_RDESC_ORIG_SIZE0 182 ··· 446 468 0x80, /* Input, */ 447 469 0xC0 /* End Collection */ 448 470 }; 449 - 450 - /* 451 - * See TWHA60 description, device and HID report descriptors at 452 - * http://sf.net/apps/mediawiki/digimend/?title=UC-Logic_Tablet_TWHA60 453 - */ 454 471 455 472 /* Size of the original descriptors of TWHA60 tablet */ 456 473 #define TWHA60_RDESC_ORIG_SIZE0 254 ··· 586 613 0xC0 /* End Collection */ 587 614 }; 588 615 616 + /* Fixed virtual pad report descriptor */ 617 + static const __u8 uclogic_buttonpad_rdesc[] = { 618 + 0x05, 0x01, /* Usage Page (Desktop), */ 619 + 0x09, 0x07, /* Usage (Keypad), */ 620 + 0xA1, 0x01, /* Collection (Application), */ 621 + 0x85, 0xF7, /* Report ID (247), */ 622 + 0x05, 0x0D, /* Usage Page (Digitizers), */ 623 + 0x09, 0x39, /* Usage (Tablet Function Keys), */ 624 + 0xA0, /* Collection (Physical), */ 625 + 0x05, 0x09, /* Usage Page (Button), */ 626 + 0x75, 0x01, /* Report Size (1), */ 627 + 0x95, 0x18, /* Report Count (24), */ 628 + 0x81, 0x03, /* Input (Constant, Variable), */ 629 + 0x19, 0x01, /* Usage Minimum (01h), */ 630 + 0x29, 0x08, /* Usage Maximum (08h), */ 631 + 0x95, 0x08, /* Report Count (8), */ 632 + 0x81, 0x02, /* Input (Variable), */ 633 + 0xC0, /* End Collection */ 634 + 0xC0 /* End Collection */ 635 + }; 636 + 589 637 /* Parameter indices */ 590 638 enum uclogic_prm { 591 639 UCLOGIC_PRM_X_LM = 1, ··· 622 628 unsigned int rsize; 623 629 bool invert_pen_inrange; 624 630 bool ignore_pen_usage; 631 + bool has_virtual_pad_interface; 625 632 }; 626 633 627 634 static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, ··· 631 636 struct usb_interface *iface = to_usb_interface(hdev->dev.parent); 632 637 __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; 633 638 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 639 + 640 + if (drvdata->rdesc != NULL) { 641 + rdesc = drvdata->rdesc; 642 + *rsize = drvdata->rsize; 643 + return rdesc; 644 + } 634 645 635 646 switch (hdev->product) { 636 647 case USB_DEVICE_ID_UCLOGIC_TABLET_PF1209: ··· 707 706 break; 708 707 } 709 708 break; 710 - default: 711 - if (drvdata->rdesc != NULL) { 712 - rdesc = drvdata->rdesc; 713 - *rsize = drvdata->rsize; 714 - } 715 709 } 716 710 717 711 return rdesc; ··· 800 804 len = UCLOGIC_PRM_NUM * sizeof(*buf); 801 805 buf = kmalloc(len, GFP_KERNEL); 802 806 if (buf == NULL) { 803 - hid_err(hdev, "failed to allocate parameter buffer\n"); 804 807 rc = -ENOMEM; 805 808 goto cleanup; 806 809 } ··· 843 848 sizeof(uclogic_tablet_rdesc_template), 844 849 GFP_KERNEL); 845 850 if (drvdata->rdesc == NULL) { 846 - hid_err(hdev, "failed to allocate fixed rdesc\n"); 847 851 rc = -ENOMEM; 848 852 goto cleanup; 849 853 } ··· 870 876 return rc; 871 877 } 872 878 879 + /** 880 + * Enable actual button mode. 881 + * 882 + * @hdev: HID device 883 + */ 884 + static int uclogic_button_enable(struct hid_device *hdev) 885 + { 886 + int rc; 887 + struct usb_device *usb_dev = hid_to_usb_dev(hdev); 888 + struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 889 + char *str_buf; 890 + size_t str_len = 16; 891 + unsigned char *rdesc; 892 + size_t rdesc_len; 893 + 894 + str_buf = kzalloc(str_len, GFP_KERNEL); 895 + if (str_buf == NULL) { 896 + rc = -ENOMEM; 897 + goto cleanup; 898 + } 899 + 900 + /* Enable abstract keyboard mode */ 901 + rc = usb_string(usb_dev, 0x7b, str_buf, str_len); 902 + if (rc == -EPIPE) { 903 + hid_info(hdev, "button mode setting not found\n"); 904 + rc = 0; 905 + goto cleanup; 906 + } else if (rc < 0) { 907 + hid_err(hdev, "failed to enable abstract keyboard\n"); 908 + goto cleanup; 909 + } else if (strncmp(str_buf, "HK On", rc)) { 910 + hid_info(hdev, "invalid answer when requesting buttons: '%s'\n", 911 + str_buf); 912 + rc = -EINVAL; 913 + goto cleanup; 914 + } 915 + 916 + /* Re-allocate fixed report descriptor */ 917 + rdesc_len = drvdata->rsize + sizeof(uclogic_buttonpad_rdesc); 918 + rdesc = devm_kzalloc(&hdev->dev, rdesc_len, GFP_KERNEL); 919 + if (!rdesc) { 920 + rc = -ENOMEM; 921 + goto cleanup; 922 + } 923 + 924 + memcpy(rdesc, drvdata->rdesc, drvdata->rsize); 925 + 926 + /* Append the buttonpad descriptor */ 927 + memcpy(rdesc + drvdata->rsize, uclogic_buttonpad_rdesc, 928 + sizeof(uclogic_buttonpad_rdesc)); 929 + 930 + /* clean up old rdesc and use the new one */ 931 + drvdata->rsize = rdesc_len; 932 + devm_kfree(&hdev->dev, drvdata->rdesc); 933 + drvdata->rdesc = rdesc; 934 + 935 + rc = 0; 936 + 937 + cleanup: 938 + kfree(str_buf); 939 + return rc; 940 + } 941 + 873 942 static int uclogic_probe(struct hid_device *hdev, 874 943 const struct hid_device_id *id) 875 944 { 876 945 int rc; 877 946 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 947 + struct usb_device *udev = hid_to_usb_dev(hdev); 878 948 struct uclogic_drvdata *drvdata; 879 949 880 950 /* ··· 957 899 958 900 switch (id->product) { 959 901 case USB_DEVICE_ID_HUION_TABLET: 902 + case USB_DEVICE_ID_YIYNOVA_TABLET: 903 + case USB_DEVICE_ID_UGEE_TABLET_81: 904 + case USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3: 905 + case USB_DEVICE_ID_UGEE_TABLET_45: 960 906 /* If this is the pen interface */ 961 907 if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { 962 908 rc = uclogic_tablet_enable(hdev); ··· 969 907 return rc; 970 908 } 971 909 drvdata->invert_pen_inrange = true; 910 + 911 + rc = uclogic_button_enable(hdev); 912 + drvdata->has_virtual_pad_interface = !rc; 972 913 } else { 973 914 drvdata->ignore_pen_usage = true; 915 + } 916 + break; 917 + case USB_DEVICE_ID_UGTIZER_TABLET_GP0610: 918 + /* If this is the pen interface */ 919 + if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { 920 + rc = uclogic_tablet_enable(hdev); 921 + if (rc) { 922 + hid_err(hdev, "tablet enabling failed\n"); 923 + return rc; 924 + } 925 + drvdata->invert_pen_inrange = true; 926 + } else { 927 + drvdata->ignore_pen_usage = true; 928 + } 929 + break; 930 + case USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60: 931 + /* 932 + * If it is the three-interface version, which is known to 933 + * respond to initialization. 934 + */ 935 + if (udev->config->desc.bNumInterfaces == 3) { 936 + /* If it is the pen interface */ 937 + if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { 938 + rc = uclogic_tablet_enable(hdev); 939 + if (rc) { 940 + hid_err(hdev, "tablet enabling failed\n"); 941 + return rc; 942 + } 943 + drvdata->invert_pen_inrange = true; 944 + 945 + rc = uclogic_button_enable(hdev); 946 + drvdata->has_virtual_pad_interface = !rc; 947 + } else { 948 + drvdata->ignore_pen_usage = true; 949 + } 974 950 } 975 951 break; 976 952 } ··· 1033 933 { 1034 934 struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); 1035 935 1036 - if ((drvdata->invert_pen_inrange) && 1037 - (report->type == HID_INPUT_REPORT) && 936 + if ((report->type == HID_INPUT_REPORT) && 1038 937 (report->id == UCLOGIC_PEN_REPORT_ID) && 1039 - (size >= 2)) 1040 - /* Invert the in-range bit */ 1041 - data[1] ^= 0x40; 938 + (size >= 2)) { 939 + if (drvdata->has_virtual_pad_interface && (data[1] & 0x20)) 940 + /* Change to virtual frame button report ID */ 941 + data[0] = 0xf7; 942 + else if (drvdata->invert_pen_inrange) 943 + /* Invert the in-range bit */ 944 + data[1] ^= 0x40; 945 + } 1042 946 1043 947 return 0; 1044 948 } ··· 1064 960 USB_DEVICE_ID_UCLOGIC_TABLET_TWHA60) }, 1065 961 { HID_USB_DEVICE(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET) }, 1066 962 { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_HUION_TABLET) }, 963 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_YIYNOVA_TABLET) }, 964 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_81) }, 965 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UGEE_TABLET_45) }, 966 + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_DRAWIMAGE_G3) }, 967 + { HID_USB_DEVICE(USB_VENDOR_ID_UGTIZER, USB_DEVICE_ID_UGTIZER_TABLET_GP0610) }, 1067 968 { } 1068 969 }; 1069 970 MODULE_DEVICE_TABLE(hid, uclogic_devices);
-36
drivers/hid/hid-waltop.c
··· 42 42 * 02 16 02 ink 43 43 */ 44 44 45 - /* 46 - * See Slim Tablet 5.8 inch description, device and HID report descriptors at 47 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_5.8%22 48 - */ 49 - 50 45 /* Size of the original report descriptor of Slim Tablet 5.8 inch */ 51 46 #define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 52 47 ··· 92 97 0xC0, /* End Collection, */ 93 98 0xC0 /* End Collection */ 94 99 }; 95 - 96 - /* 97 - * See Slim Tablet 12.1 inch description, device and HID report descriptors at 98 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Slim_Tablet_12.1%22 99 - */ 100 100 101 101 /* Size of the original report descriptor of Slim Tablet 12.1 inch */ 102 102 #define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269 ··· 144 154 0xC0 /* End Collection */ 145 155 }; 146 156 147 - /* 148 - * See Q Pad description, device and HID report descriptors at 149 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Q_Pad 150 - */ 151 - 152 157 /* Size of the original report descriptor of Q Pad */ 153 158 #define Q_PAD_RDESC_ORIG_SIZE 241 154 159 ··· 194 209 0xC0, /* End Collection, */ 195 210 0xC0 /* End Collection */ 196 211 }; 197 - 198 - /* 199 - * See description, device and HID report descriptors of tablet with PID 0038 at 200 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_PID_0038 201 - */ 202 212 203 213 /* Size of the original report descriptor of tablet with PID 0038 */ 204 214 #define PID_0038_RDESC_ORIG_SIZE 241 ··· 247 267 0xC0, /* End Collection, */ 248 268 0xC0 /* End Collection */ 249 269 }; 250 - 251 - /* 252 - * See Media Tablet 10.6 inch description, device and HID report descriptors at 253 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_10.6%22 254 - */ 255 270 256 271 /* Size of the original report descriptor of Media Tablet 10.6 inch */ 257 272 #define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 ··· 361 386 0xC0 /* End Collection */ 362 387 }; 363 388 364 - /* 365 - * See Media Tablet 14.1 inch description, device and HID report descriptors at 366 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Media_Tablet_14.1%22 367 - */ 368 - 369 389 /* Size of the original report descriptor of Media Tablet 14.1 inch */ 370 390 #define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309 371 391 ··· 471 501 0x81, 0x03, /* Input (Constant, Variable), */ 472 502 0xC0 /* End Collection */ 473 503 }; 474 - 475 - /* 476 - * See Sirius Battery Free Tablet description, device and HID report descriptors 477 - * at 478 - * http://sf.net/apps/mediawiki/digimend/?title=Waltop_Sirius_Battery_Free_Tablet 479 - */ 480 504 481 505 /* Size of the original report descriptor of Sirius Battery Free Tablet */ 482 506 #define SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE 335
+17
drivers/hid/intel-ish-hid/Kconfig
··· 1 + menu "Intel ISH HID support" 2 + depends on X86_64 && PCI 3 + 4 + config INTEL_ISH_HID 5 + tristate "Intel Integrated Sensor Hub" 6 + default n 7 + select HID 8 + help 9 + The Integrated Sensor Hub (ISH) enables the ability to offload 10 + sensor polling and algorithm processing to a dedicated low power 11 + processor in the chipset. This allows the core processor to go into 12 + low power modes more often, resulting in the increased battery life. 13 + The current processors that support ISH are: Cherrytrail, Skylake, 14 + Broxton and Kaby Lake. 15 + 16 + Say Y here if you want to support Intel ISH. If unsure, say N. 17 + endmenu
+22
drivers/hid/intel-ish-hid/Makefile
··· 1 + # 2 + # Makefile - Intel ISH HID drivers 3 + # Copyright (c) 2014-2016, Intel Corporation. 4 + # 5 + # 6 + obj-$(CONFIG_INTEL_ISH_HID) += intel-ishtp.o 7 + intel-ishtp-objs := ishtp/init.o 8 + intel-ishtp-objs += ishtp/hbm.o 9 + intel-ishtp-objs += ishtp/client.o 10 + intel-ishtp-objs += ishtp/bus.o 11 + intel-ishtp-objs += ishtp/dma-if.o 12 + intel-ishtp-objs += ishtp/client-buffers.o 13 + 14 + obj-$(CONFIG_INTEL_ISH_HID) += intel-ish-ipc.o 15 + intel-ish-ipc-objs := ipc/ipc.o 16 + intel-ish-ipc-objs += ipc/pci-ish.o 17 + 18 + obj-$(CONFIG_INTEL_ISH_HID) += intel-ishtp-hid.o 19 + intel-ishtp-hid-objs := ishtp-hid.o 20 + intel-ishtp-hid-objs += ishtp-hid-client.o 21 + 22 + ccflags-y += -Idrivers/hid/intel-ish-hid/ishtp
+220
drivers/hid/intel-ish-hid/ipc/hw-ish-regs.h
··· 1 + /* 2 + * ISH registers definitions 3 + * 4 + * Copyright (c) 2012-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #ifndef _ISHTP_ISH_REGS_H_ 17 + #define _ISHTP_ISH_REGS_H_ 18 + 19 + 20 + /*** IPC PCI Offsets and sizes ***/ 21 + /* ISH IPC Base Address */ 22 + #define IPC_REG_BASE 0x0000 23 + /* Peripheral Interrupt Status Register */ 24 + #define IPC_REG_PISR_CHV_AB (IPC_REG_BASE + 0x00) 25 + /* Peripheral Interrupt Mask Register */ 26 + #define IPC_REG_PIMR_CHV_AB (IPC_REG_BASE + 0x04) 27 + /*BXT, CHV_K0*/ 28 + /*Peripheral Interrupt Status Register */ 29 + #define IPC_REG_PISR_BXT (IPC_REG_BASE + 0x0C) 30 + /*Peripheral Interrupt Mask Register */ 31 + #define IPC_REG_PIMR_BXT (IPC_REG_BASE + 0x08) 32 + /***********************************/ 33 + /* ISH Host Firmware status Register */ 34 + #define IPC_REG_ISH_HOST_FWSTS (IPC_REG_BASE + 0x34) 35 + /* Host Communication Register */ 36 + #define IPC_REG_HOST_COMM (IPC_REG_BASE + 0x38) 37 + /* Reset register */ 38 + #define IPC_REG_ISH_RST (IPC_REG_BASE + 0x44) 39 + 40 + /* Inbound doorbell register Host to ISH */ 41 + #define IPC_REG_HOST2ISH_DRBL (IPC_REG_BASE + 0x48) 42 + /* Outbound doorbell register ISH to Host */ 43 + #define IPC_REG_ISH2HOST_DRBL (IPC_REG_BASE + 0x54) 44 + /* ISH to HOST message registers */ 45 + #define IPC_REG_ISH2HOST_MSG (IPC_REG_BASE + 0x60) 46 + /* HOST to ISH message registers */ 47 + #define IPC_REG_HOST2ISH_MSG (IPC_REG_BASE + 0xE0) 48 + /* REMAP2 to enable DMA (D3 RCR) */ 49 + #define IPC_REG_ISH_RMP2 (IPC_REG_BASE + 0x368) 50 + 51 + #define IPC_REG_MAX (IPC_REG_BASE + 0x400) 52 + 53 + /*** register bits - HISR ***/ 54 + /* bit corresponds HOST2ISH interrupt in PISR and PIMR registers */ 55 + #define IPC_INT_HOST2ISH_BIT (1<<0) 56 + /***********************************/ 57 + /*CHV_A0, CHV_B0*/ 58 + /* bit corresponds ISH2HOST interrupt in PISR and PIMR registers */ 59 + #define IPC_INT_ISH2HOST_BIT_CHV_AB (1<<3) 60 + /*BXT, CHV_K0*/ 61 + /* bit corresponds ISH2HOST interrupt in PISR and PIMR registers */ 62 + #define IPC_INT_ISH2HOST_BIT_BXT (1<<0) 63 + /***********************************/ 64 + 65 + /* bit corresponds ISH2HOST busy clear interrupt in PIMR register */ 66 + #define IPC_INT_ISH2HOST_CLR_MASK_BIT (1<<11) 67 + 68 + /* offset of ISH2HOST busy clear interrupt in IPC_BUSY_CLR register */ 69 + #define IPC_INT_ISH2HOST_CLR_OFFS (0) 70 + 71 + /* bit corresponds ISH2HOST busy clear interrupt in IPC_BUSY_CLR register */ 72 + #define IPC_INT_ISH2HOST_CLR_BIT (1<<IPC_INT_ISH2HOST_CLR_OFFS) 73 + 74 + /* bit corresponds busy bit in doorbell registers */ 75 + #define IPC_DRBL_BUSY_OFFS (31) 76 + #define IPC_DRBL_BUSY_BIT (1<<IPC_DRBL_BUSY_OFFS) 77 + 78 + #define IPC_HOST_OWNS_MSG_OFFS (30) 79 + 80 + /* 81 + * A0: bit means that host owns MSGnn registers and is reading them. 82 + * ISH FW may not write to them 83 + */ 84 + #define IPC_HOST_OWNS_MSG_BIT (1<<IPC_HOST_OWNS_MSG_OFFS) 85 + 86 + /* 87 + * Host status bits (HOSTCOMM) 88 + */ 89 + /* bit corresponds host ready bit in Host Status Register (HOST_COMM) */ 90 + #define IPC_HOSTCOMM_READY_OFFS (7) 91 + #define IPC_HOSTCOMM_READY_BIT (1<<IPC_HOSTCOMM_READY_OFFS) 92 + 93 + /***********************************/ 94 + /*CHV_A0, CHV_B0*/ 95 + #define IPC_HOSTCOMM_INT_EN_OFFS_CHV_AB (31) 96 + #define IPC_HOSTCOMM_INT_EN_BIT_CHV_AB \ 97 + (1<<IPC_HOSTCOMM_INT_EN_OFFS_CHV_AB) 98 + /*BXT, CHV_K0*/ 99 + #define IPC_PIMR_INT_EN_OFFS_BXT (0) 100 + #define IPC_PIMR_INT_EN_BIT_BXT (1<<IPC_PIMR_INT_EN_OFFS_BXT) 101 + 102 + #define IPC_HOST2ISH_BUSYCLEAR_MASK_OFFS_BXT (8) 103 + #define IPC_HOST2ISH_BUSYCLEAR_MASK_BIT \ 104 + (1<<IPC_HOST2ISH_BUSYCLEAR_MASK_OFFS_BXT) 105 + /***********************************/ 106 + /* 107 + * both Host and ISH have ILUP at bit 0 108 + * bit corresponds host ready bit in both status registers 109 + */ 110 + #define IPC_ILUP_OFFS (0) 111 + #define IPC_ILUP_BIT (1<<IPC_ILUP_OFFS) 112 + 113 + /* 114 + * FW status bits (relevant) 115 + */ 116 + #define IPC_FWSTS_ILUP 0x1 117 + #define IPC_FWSTS_ISHTP_UP (1<<1) 118 + #define IPC_FWSTS_DMA0 (1<<16) 119 + #define IPC_FWSTS_DMA1 (1<<17) 120 + #define IPC_FWSTS_DMA2 (1<<18) 121 + #define IPC_FWSTS_DMA3 (1<<19) 122 + 123 + #define IPC_ISH_IN_DMA \ 124 + (IPC_FWSTS_DMA0 | IPC_FWSTS_DMA1 | IPC_FWSTS_DMA2 | IPC_FWSTS_DMA3) 125 + 126 + /* bit corresponds host ready bit in ISH FW Status Register */ 127 + #define IPC_ISH_ISHTP_READY_OFFS (1) 128 + #define IPC_ISH_ISHTP_READY_BIT (1<<IPC_ISH_ISHTP_READY_OFFS) 129 + 130 + #define IPC_RMP2_DMA_ENABLED 0x1 /* Value to enable DMA, per D3 RCR */ 131 + 132 + #define IPC_MSG_MAX_SIZE 0x80 133 + 134 + 135 + #define IPC_HEADER_LENGTH_MASK 0x03FF 136 + #define IPC_HEADER_PROTOCOL_MASK 0x0F 137 + #define IPC_HEADER_MNG_CMD_MASK 0x0F 138 + 139 + #define IPC_HEADER_LENGTH_OFFSET 0 140 + #define IPC_HEADER_PROTOCOL_OFFSET 10 141 + #define IPC_HEADER_MNG_CMD_OFFSET 16 142 + 143 + #define IPC_HEADER_GET_LENGTH(drbl_reg) \ 144 + (((drbl_reg) >> IPC_HEADER_LENGTH_OFFSET)&IPC_HEADER_LENGTH_MASK) 145 + #define IPC_HEADER_GET_PROTOCOL(drbl_reg) \ 146 + (((drbl_reg) >> IPC_HEADER_PROTOCOL_OFFSET)&IPC_HEADER_PROTOCOL_MASK) 147 + #define IPC_HEADER_GET_MNG_CMD(drbl_reg) \ 148 + (((drbl_reg) >> IPC_HEADER_MNG_CMD_OFFSET)&IPC_HEADER_MNG_CMD_MASK) 149 + 150 + #define IPC_IS_BUSY(drbl_reg) \ 151 + (((drbl_reg)&IPC_DRBL_BUSY_BIT) == ((uint32_t)IPC_DRBL_BUSY_BIT)) 152 + 153 + /***********************************/ 154 + /*CHV_A0, CHV_B0*/ 155 + #define IPC_INT_FROM_ISH_TO_HOST_CHV_AB(drbl_reg) \ 156 + (((drbl_reg)&IPC_INT_ISH2HOST_BIT_CHV_AB) == \ 157 + ((u32)IPC_INT_ISH2HOST_BIT_CHV_AB)) 158 + /*BXT, CHV_K0*/ 159 + #define IPC_INT_FROM_ISH_TO_HOST_BXT(drbl_reg) \ 160 + (((drbl_reg)&IPC_INT_ISH2HOST_BIT_BXT) == \ 161 + ((u32)IPC_INT_ISH2HOST_BIT_BXT)) 162 + /***********************************/ 163 + 164 + #define IPC_BUILD_HEADER(length, protocol, busy) \ 165 + (((busy)<<IPC_DRBL_BUSY_OFFS) | \ 166 + ((protocol) << IPC_HEADER_PROTOCOL_OFFSET) | \ 167 + ((length)<<IPC_HEADER_LENGTH_OFFSET)) 168 + 169 + #define IPC_BUILD_MNG_MSG(cmd, length) \ 170 + (((1)<<IPC_DRBL_BUSY_OFFS)| \ 171 + ((IPC_PROTOCOL_MNG)<<IPC_HEADER_PROTOCOL_OFFSET)| \ 172 + ((cmd)<<IPC_HEADER_MNG_CMD_OFFSET)| \ 173 + ((length)<<IPC_HEADER_LENGTH_OFFSET)) 174 + 175 + 176 + #define IPC_SET_HOST_READY(host_status) \ 177 + ((host_status) |= (IPC_HOSTCOMM_READY_BIT)) 178 + 179 + #define IPC_SET_HOST_ILUP(host_status) \ 180 + ((host_status) |= (IPC_ILUP_BIT)) 181 + 182 + #define IPC_CLEAR_HOST_READY(host_status) \ 183 + ((host_status) ^= (IPC_HOSTCOMM_READY_BIT)) 184 + 185 + #define IPC_CLEAR_HOST_ILUP(host_status) \ 186 + ((host_status) ^= (IPC_ILUP_BIT)) 187 + 188 + /* todo - temp until PIMR HW ready */ 189 + #define IPC_HOST_BUSY_READING_OFFS 6 190 + 191 + /* bit corresponds host ready bit in Host Status Register (HOST_COMM) */ 192 + #define IPC_HOST_BUSY_READING_BIT (1<<IPC_HOST_BUSY_READING_OFFS) 193 + 194 + #define IPC_SET_HOST_BUSY_READING(host_status) \ 195 + ((host_status) |= (IPC_HOST_BUSY_READING_BIT)) 196 + 197 + #define IPC_CLEAR_HOST_BUSY_READING(host_status)\ 198 + ((host_status) ^= (IPC_HOST_BUSY_READING_BIT)) 199 + 200 + 201 + #define IPC_IS_ISH_ISHTP_READY(ish_status) \ 202 + (((ish_status) & IPC_ISH_ISHTP_READY_BIT) == \ 203 + ((uint32_t)IPC_ISH_ISHTP_READY_BIT)) 204 + 205 + #define IPC_IS_ISH_ILUP(ish_status) \ 206 + (((ish_status) & IPC_ILUP_BIT) == ((uint32_t)IPC_ILUP_BIT)) 207 + 208 + 209 + #define IPC_PROTOCOL_ISHTP 1 210 + #define IPC_PROTOCOL_MNG 3 211 + 212 + #define MNG_RX_CMPL_ENABLE 0 213 + #define MNG_RX_CMPL_DISABLE 1 214 + #define MNG_RX_CMPL_INDICATION 2 215 + #define MNG_RESET_NOTIFY 3 216 + #define MNG_RESET_NOTIFY_ACK 4 217 + #define MNG_SYNC_FW_CLOCK 5 218 + #define MNG_ILLEGAL_CMD 0xFF 219 + 220 + #endif /* _ISHTP_ISH_REGS_H_ */
+71
drivers/hid/intel-ish-hid/ipc/hw-ish.h
··· 1 + /* 2 + * H/W layer of ISHTP provider device (ISH) 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #ifndef _ISHTP_HW_ISH_H_ 17 + #define _ISHTP_HW_ISH_H_ 18 + 19 + #include <linux/pci.h> 20 + #include <linux/interrupt.h> 21 + #include "hw-ish-regs.h" 22 + #include "ishtp-dev.h" 23 + 24 + #define CHV_DEVICE_ID 0x22D8 25 + #define BXT_Ax_DEVICE_ID 0x0AA2 26 + #define BXT_Bx_DEVICE_ID 0x1AA2 27 + #define APL_Ax_DEVICE_ID 0x5AA2 28 + #define SPT_Ax_DEVICE_ID 0x9D35 29 + 30 + #define REVISION_ID_CHT_A0 0x6 31 + #define REVISION_ID_CHT_Ax_SI 0x0 32 + #define REVISION_ID_CHT_Bx_SI 0x10 33 + #define REVISION_ID_CHT_Kx_SI 0x20 34 + #define REVISION_ID_CHT_Dx_SI 0x30 35 + #define REVISION_ID_CHT_B0 0xB0 36 + #define REVISION_ID_SI_MASK 0x70 37 + 38 + struct ipc_rst_payload_type { 39 + uint16_t reset_id; 40 + uint16_t reserved; 41 + }; 42 + 43 + struct time_sync_format { 44 + uint8_t ts1_source; 45 + uint8_t ts2_source; 46 + uint16_t reserved; 47 + } __packed; 48 + 49 + struct ipc_time_update_msg { 50 + uint64_t primary_host_time; 51 + struct time_sync_format sync_info; 52 + uint64_t secondary_host_time; 53 + } __packed; 54 + 55 + enum { 56 + HOST_UTC_TIME_USEC = 0, 57 + HOST_SYSTEM_TIME_USEC = 1 58 + }; 59 + 60 + struct ish_hw { 61 + void __iomem *mem_addr; 62 + }; 63 + 64 + #define to_ish_hw(dev) (struct ish_hw *)((dev)->hw) 65 + 66 + irqreturn_t ish_irq_handler(int irq, void *dev_id); 67 + struct ishtp_device *ish_dev_init(struct pci_dev *pdev); 68 + int ish_hw_start(struct ishtp_device *dev); 69 + void ish_device_disable(struct ishtp_device *dev); 70 + 71 + #endif /* _ISHTP_HW_ISH_H_ */
+881
drivers/hid/intel-ish-hid/ipc/ipc.c
··· 1 + /* 2 + * H/W layer of ISHTP provider device (ISH) 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include <linux/sched.h> 17 + #include <linux/spinlock.h> 18 + #include <linux/delay.h> 19 + #include <linux/jiffies.h> 20 + #include "client.h" 21 + #include "hw-ish.h" 22 + #include "utils.h" 23 + #include "hbm.h" 24 + 25 + /* For FW reset flow */ 26 + static struct work_struct fw_reset_work; 27 + static struct ishtp_device *ishtp_dev; 28 + 29 + /** 30 + * ish_reg_read() - Read register 31 + * @dev: ISHTP device pointer 32 + * @offset: Register offset 33 + * 34 + * Read 32 bit register at a given offset 35 + * 36 + * Return: Read register value 37 + */ 38 + static inline uint32_t ish_reg_read(const struct ishtp_device *dev, 39 + unsigned long offset) 40 + { 41 + struct ish_hw *hw = to_ish_hw(dev); 42 + 43 + return readl(hw->mem_addr + offset); 44 + } 45 + 46 + /** 47 + * ish_reg_write() - Write register 48 + * @dev: ISHTP device pointer 49 + * @offset: Register offset 50 + * @value: Value to write 51 + * 52 + * Writes 32 bit register at a give offset 53 + */ 54 + static inline void ish_reg_write(struct ishtp_device *dev, 55 + unsigned long offset, 56 + uint32_t value) 57 + { 58 + struct ish_hw *hw = to_ish_hw(dev); 59 + 60 + writel(value, hw->mem_addr + offset); 61 + } 62 + 63 + /** 64 + * _ish_read_fw_sts_reg() - Read FW status register 65 + * @dev: ISHTP device pointer 66 + * 67 + * Read FW status register 68 + * 69 + * Return: Read register value 70 + */ 71 + static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev) 72 + { 73 + return ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 74 + } 75 + 76 + /** 77 + * check_generated_interrupt() - Check if ISH interrupt 78 + * @dev: ISHTP device pointer 79 + * 80 + * Check if an interrupt was generated for ISH 81 + * 82 + * Return: Read true or false 83 + */ 84 + static bool check_generated_interrupt(struct ishtp_device *dev) 85 + { 86 + bool interrupt_generated = true; 87 + uint32_t pisr_val = 0; 88 + 89 + if (dev->pdev->device == CHV_DEVICE_ID) { 90 + pisr_val = ish_reg_read(dev, IPC_REG_PISR_CHV_AB); 91 + interrupt_generated = 92 + IPC_INT_FROM_ISH_TO_HOST_CHV_AB(pisr_val); 93 + } else { 94 + pisr_val = ish_reg_read(dev, IPC_REG_PISR_BXT); 95 + interrupt_generated = IPC_INT_FROM_ISH_TO_HOST_BXT(pisr_val); 96 + } 97 + 98 + return interrupt_generated; 99 + } 100 + 101 + /** 102 + * ish_is_input_ready() - Check if FW ready for RX 103 + * @dev: ISHTP device pointer 104 + * 105 + * Check if ISH FW is ready for receiving data 106 + * 107 + * Return: Read true or false 108 + */ 109 + static bool ish_is_input_ready(struct ishtp_device *dev) 110 + { 111 + uint32_t doorbell_val; 112 + 113 + doorbell_val = ish_reg_read(dev, IPC_REG_HOST2ISH_DRBL); 114 + return !IPC_IS_BUSY(doorbell_val); 115 + } 116 + 117 + /** 118 + * set_host_ready() - Indicate host ready 119 + * @dev: ISHTP device pointer 120 + * 121 + * Set host ready indication to FW 122 + */ 123 + static void set_host_ready(struct ishtp_device *dev) 124 + { 125 + if (dev->pdev->device == CHV_DEVICE_ID) { 126 + if (dev->pdev->revision == REVISION_ID_CHT_A0 || 127 + (dev->pdev->revision & REVISION_ID_SI_MASK) == 128 + REVISION_ID_CHT_Ax_SI) 129 + ish_reg_write(dev, IPC_REG_HOST_COMM, 0x81); 130 + else if (dev->pdev->revision == REVISION_ID_CHT_B0 || 131 + (dev->pdev->revision & REVISION_ID_SI_MASK) == 132 + REVISION_ID_CHT_Bx_SI || 133 + (dev->pdev->revision & REVISION_ID_SI_MASK) == 134 + REVISION_ID_CHT_Kx_SI || 135 + (dev->pdev->revision & REVISION_ID_SI_MASK) == 136 + REVISION_ID_CHT_Dx_SI) { 137 + uint32_t host_comm_val; 138 + 139 + host_comm_val = ish_reg_read(dev, IPC_REG_HOST_COMM); 140 + host_comm_val |= IPC_HOSTCOMM_INT_EN_BIT_CHV_AB | 0x81; 141 + ish_reg_write(dev, IPC_REG_HOST_COMM, host_comm_val); 142 + } 143 + } else { 144 + uint32_t host_pimr_val; 145 + 146 + host_pimr_val = ish_reg_read(dev, IPC_REG_PIMR_BXT); 147 + host_pimr_val |= IPC_PIMR_INT_EN_BIT_BXT; 148 + /* 149 + * disable interrupt generated instead of 150 + * RX_complete_msg 151 + */ 152 + host_pimr_val &= ~IPC_HOST2ISH_BUSYCLEAR_MASK_BIT; 153 + 154 + ish_reg_write(dev, IPC_REG_PIMR_BXT, host_pimr_val); 155 + } 156 + } 157 + 158 + /** 159 + * ishtp_fw_is_ready() - Check if FW ready 160 + * @dev: ISHTP device pointer 161 + * 162 + * Check if ISH FW is ready 163 + * 164 + * Return: Read true or false 165 + */ 166 + static bool ishtp_fw_is_ready(struct ishtp_device *dev) 167 + { 168 + uint32_t ish_status = _ish_read_fw_sts_reg(dev); 169 + 170 + return IPC_IS_ISH_ILUP(ish_status) && 171 + IPC_IS_ISH_ISHTP_READY(ish_status); 172 + } 173 + 174 + /** 175 + * ish_set_host_rdy() - Indicate host ready 176 + * @dev: ISHTP device pointer 177 + * 178 + * Set host ready indication to FW 179 + */ 180 + static void ish_set_host_rdy(struct ishtp_device *dev) 181 + { 182 + uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM); 183 + 184 + IPC_SET_HOST_READY(host_status); 185 + ish_reg_write(dev, IPC_REG_HOST_COMM, host_status); 186 + } 187 + 188 + /** 189 + * ish_clr_host_rdy() - Indicate host not ready 190 + * @dev: ISHTP device pointer 191 + * 192 + * Send host not ready indication to FW 193 + */ 194 + static void ish_clr_host_rdy(struct ishtp_device *dev) 195 + { 196 + uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM); 197 + 198 + IPC_CLEAR_HOST_READY(host_status); 199 + ish_reg_write(dev, IPC_REG_HOST_COMM, host_status); 200 + } 201 + 202 + /** 203 + * _ishtp_read_hdr() - Read message header 204 + * @dev: ISHTP device pointer 205 + * 206 + * Read header of 32bit length 207 + * 208 + * Return: Read register value 209 + */ 210 + static uint32_t _ishtp_read_hdr(const struct ishtp_device *dev) 211 + { 212 + return ish_reg_read(dev, IPC_REG_ISH2HOST_MSG); 213 + } 214 + 215 + /** 216 + * _ishtp_read - Read message 217 + * @dev: ISHTP device pointer 218 + * @buffer: message buffer 219 + * @buffer_length: length of message buffer 220 + * 221 + * Read message from FW 222 + * 223 + * Return: Always 0 224 + */ 225 + static int _ishtp_read(struct ishtp_device *dev, unsigned char *buffer, 226 + unsigned long buffer_length) 227 + { 228 + uint32_t i; 229 + uint32_t *r_buf = (uint32_t *)buffer; 230 + uint32_t msg_offs; 231 + 232 + msg_offs = IPC_REG_ISH2HOST_MSG + sizeof(struct ishtp_msg_hdr); 233 + for (i = 0; i < buffer_length; i += sizeof(uint32_t)) 234 + *r_buf++ = ish_reg_read(dev, msg_offs + i); 235 + 236 + return 0; 237 + } 238 + 239 + /** 240 + * write_ipc_from_queue() - try to write ipc msg from Tx queue to device 241 + * @dev: ishtp device pointer 242 + * 243 + * Check if DRBL is cleared. if it is - write the first IPC msg, then call 244 + * the callback function (unless it's NULL) 245 + * 246 + * Return: 0 for success else failure code 247 + */ 248 + static int write_ipc_from_queue(struct ishtp_device *dev) 249 + { 250 + struct wr_msg_ctl_info *ipc_link; 251 + unsigned long length; 252 + unsigned long rem; 253 + unsigned long flags; 254 + uint32_t doorbell_val; 255 + uint32_t *r_buf; 256 + uint32_t reg_addr; 257 + int i; 258 + void (*ipc_send_compl)(void *); 259 + void *ipc_send_compl_prm; 260 + static int out_ipc_locked; 261 + unsigned long out_ipc_flags; 262 + 263 + if (dev->dev_state == ISHTP_DEV_DISABLED) 264 + return -EINVAL; 265 + 266 + spin_lock_irqsave(&dev->out_ipc_spinlock, out_ipc_flags); 267 + if (out_ipc_locked) { 268 + spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); 269 + return -EBUSY; 270 + } 271 + out_ipc_locked = 1; 272 + if (!ish_is_input_ready(dev)) { 273 + out_ipc_locked = 0; 274 + spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); 275 + return -EBUSY; 276 + } 277 + spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); 278 + 279 + spin_lock_irqsave(&dev->wr_processing_spinlock, flags); 280 + /* 281 + * if tx send list is empty - return 0; 282 + * may happen, as RX_COMPLETE handler doesn't check list emptiness. 283 + */ 284 + if (list_empty(&dev->wr_processing_list_head.link)) { 285 + spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 286 + out_ipc_locked = 0; 287 + return 0; 288 + } 289 + 290 + ipc_link = list_entry(dev->wr_processing_list_head.link.next, 291 + struct wr_msg_ctl_info, link); 292 + /* first 4 bytes of the data is the doorbell value (IPC header) */ 293 + length = ipc_link->length - sizeof(uint32_t); 294 + doorbell_val = *(uint32_t *)ipc_link->inline_data; 295 + r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t)); 296 + 297 + /* If sending MNG_SYNC_FW_CLOCK, update clock again */ 298 + if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG && 299 + IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) { 300 + struct timespec ts_system; 301 + struct timeval tv_utc; 302 + uint64_t usec_system, usec_utc; 303 + struct ipc_time_update_msg time_update; 304 + struct time_sync_format ts_format; 305 + 306 + get_monotonic_boottime(&ts_system); 307 + do_gettimeofday(&tv_utc); 308 + usec_system = (timespec_to_ns(&ts_system)) / NSEC_PER_USEC; 309 + usec_utc = (uint64_t)tv_utc.tv_sec * 1000000 + 310 + ((uint32_t)tv_utc.tv_usec); 311 + ts_format.ts1_source = HOST_SYSTEM_TIME_USEC; 312 + ts_format.ts2_source = HOST_UTC_TIME_USEC; 313 + 314 + time_update.primary_host_time = usec_system; 315 + time_update.secondary_host_time = usec_utc; 316 + time_update.sync_info = ts_format; 317 + 318 + memcpy(r_buf, &time_update, 319 + sizeof(struct ipc_time_update_msg)); 320 + } 321 + 322 + for (i = 0, reg_addr = IPC_REG_HOST2ISH_MSG; i < length >> 2; i++, 323 + reg_addr += 4) 324 + ish_reg_write(dev, reg_addr, r_buf[i]); 325 + 326 + rem = length & 0x3; 327 + if (rem > 0) { 328 + uint32_t reg = 0; 329 + 330 + memcpy(&reg, &r_buf[length >> 2], rem); 331 + ish_reg_write(dev, reg_addr, reg); 332 + } 333 + /* Flush writes to msg registers and doorbell */ 334 + ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 335 + 336 + /* Update IPC counters */ 337 + ++dev->ipc_tx_cnt; 338 + dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); 339 + 340 + ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val); 341 + out_ipc_locked = 0; 342 + 343 + ipc_send_compl = ipc_link->ipc_send_compl; 344 + ipc_send_compl_prm = ipc_link->ipc_send_compl_prm; 345 + list_del_init(&ipc_link->link); 346 + list_add_tail(&ipc_link->link, &dev->wr_free_list_head.link); 347 + spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 348 + 349 + /* 350 + * callback will be called out of spinlock, 351 + * after ipc_link returned to free list 352 + */ 353 + if (ipc_send_compl) 354 + ipc_send_compl(ipc_send_compl_prm); 355 + 356 + return 0; 357 + } 358 + 359 + /** 360 + * write_ipc_to_queue() - write ipc msg to Tx queue 361 + * @dev: ishtp device instance 362 + * @ipc_send_compl: Send complete callback 363 + * @ipc_send_compl_prm: Parameter to send in complete callback 364 + * @msg: Pointer to message 365 + * @length: Length of message 366 + * 367 + * Recived msg with IPC (and upper protocol) header and add it to the device 368 + * Tx-to-write list then try to send the first IPC waiting msg 369 + * (if DRBL is cleared) 370 + * This function returns negative value for failure (means free list 371 + * is empty, or msg too long) and 0 for success. 372 + * 373 + * Return: 0 for success else failure code 374 + */ 375 + static int write_ipc_to_queue(struct ishtp_device *dev, 376 + void (*ipc_send_compl)(void *), void *ipc_send_compl_prm, 377 + unsigned char *msg, int length) 378 + { 379 + struct wr_msg_ctl_info *ipc_link; 380 + unsigned long flags; 381 + 382 + if (length > IPC_FULL_MSG_SIZE) 383 + return -EMSGSIZE; 384 + 385 + spin_lock_irqsave(&dev->wr_processing_spinlock, flags); 386 + if (list_empty(&dev->wr_free_list_head.link)) { 387 + spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 388 + return -ENOMEM; 389 + } 390 + ipc_link = list_entry(dev->wr_free_list_head.link.next, 391 + struct wr_msg_ctl_info, link); 392 + list_del_init(&ipc_link->link); 393 + 394 + ipc_link->ipc_send_compl = ipc_send_compl; 395 + ipc_link->ipc_send_compl_prm = ipc_send_compl_prm; 396 + ipc_link->length = length; 397 + memcpy(ipc_link->inline_data, msg, length); 398 + 399 + list_add_tail(&ipc_link->link, &dev->wr_processing_list_head.link); 400 + spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 401 + 402 + write_ipc_from_queue(dev); 403 + 404 + return 0; 405 + } 406 + 407 + /** 408 + * ipc_send_mng_msg() - Send management message 409 + * @dev: ishtp device instance 410 + * @msg_code: Message code 411 + * @msg: Pointer to message 412 + * @size: Length of message 413 + * 414 + * Send management message to FW 415 + * 416 + * Return: 0 for success else failure code 417 + */ 418 + static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code, 419 + void *msg, size_t size) 420 + { 421 + unsigned char ipc_msg[IPC_FULL_MSG_SIZE]; 422 + uint32_t drbl_val = IPC_BUILD_MNG_MSG(msg_code, size); 423 + 424 + memcpy(ipc_msg, &drbl_val, sizeof(uint32_t)); 425 + memcpy(ipc_msg + sizeof(uint32_t), msg, size); 426 + return write_ipc_to_queue(dev, NULL, NULL, ipc_msg, 427 + sizeof(uint32_t) + size); 428 + } 429 + 430 + /** 431 + * ish_fw_reset_handler() - FW reset handler 432 + * @dev: ishtp device pointer 433 + * 434 + * Handle FW reset 435 + * 436 + * Return: 0 for success else failure code 437 + */ 438 + static int ish_fw_reset_handler(struct ishtp_device *dev) 439 + { 440 + uint32_t reset_id; 441 + unsigned long flags; 442 + struct wr_msg_ctl_info *processing, *next; 443 + 444 + /* Read reset ID */ 445 + reset_id = ish_reg_read(dev, IPC_REG_ISH2HOST_MSG) & 0xFFFF; 446 + 447 + /* Clear IPC output queue */ 448 + spin_lock_irqsave(&dev->wr_processing_spinlock, flags); 449 + list_for_each_entry_safe(processing, next, 450 + &dev->wr_processing_list_head.link, link) { 451 + list_move_tail(&processing->link, &dev->wr_free_list_head.link); 452 + } 453 + spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 454 + 455 + /* ISHTP notification in IPC_RESET */ 456 + ishtp_reset_handler(dev); 457 + 458 + if (!ish_is_input_ready(dev)) 459 + timed_wait_for_timeout(WAIT_FOR_SEND_SLICE, 460 + ish_is_input_ready(dev), (2 * HZ)); 461 + 462 + /* ISH FW is dead */ 463 + if (!ish_is_input_ready(dev)) 464 + return -EPIPE; 465 + /* 466 + * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending 467 + * RESET_NOTIFY_ACK - FW will be checking for it 468 + */ 469 + ish_set_host_rdy(dev); 470 + /* Send RESET_NOTIFY_ACK (with reset_id) */ 471 + ipc_send_mng_msg(dev, MNG_RESET_NOTIFY_ACK, &reset_id, 472 + sizeof(uint32_t)); 473 + 474 + /* Wait for ISH FW'es ILUP and ISHTP_READY */ 475 + timed_wait_for_timeout(WAIT_FOR_SEND_SLICE, ishtp_fw_is_ready(dev), 476 + (2 * HZ)); 477 + if (!ishtp_fw_is_ready(dev)) { 478 + /* ISH FW is dead */ 479 + uint32_t ish_status; 480 + 481 + ish_status = _ish_read_fw_sts_reg(dev); 482 + dev_err(dev->devc, 483 + "[ishtp-ish]: completed reset, ISH is dead (FWSTS = %08X)\n", 484 + ish_status); 485 + return -ENODEV; 486 + } 487 + return 0; 488 + } 489 + 490 + /** 491 + * ish_fw_reset_work_fn() - FW reset worker function 492 + * @unused: not used 493 + * 494 + * Call ish_fw_reset_handler to complete FW reset 495 + */ 496 + static void fw_reset_work_fn(struct work_struct *unused) 497 + { 498 + int rv; 499 + 500 + rv = ish_fw_reset_handler(ishtp_dev); 501 + if (!rv) { 502 + /* ISH is ILUP & ISHTP-ready. Restart ISHTP */ 503 + schedule_timeout(HZ / 3); 504 + ishtp_dev->recvd_hw_ready = 1; 505 + wake_up_interruptible(&ishtp_dev->wait_hw_ready); 506 + 507 + /* ISHTP notification in IPC_RESET sequence completion */ 508 + ishtp_reset_compl_handler(ishtp_dev); 509 + } else 510 + dev_err(ishtp_dev->devc, "[ishtp-ish]: FW reset failed (%d)\n", 511 + rv); 512 + } 513 + 514 + /** 515 + * _ish_sync_fw_clock() -Sync FW clock with the OS clock 516 + * @dev: ishtp device pointer 517 + * 518 + * Sync FW and OS time 519 + */ 520 + static void _ish_sync_fw_clock(struct ishtp_device *dev) 521 + { 522 + static unsigned long prev_sync; 523 + struct timespec ts; 524 + uint64_t usec; 525 + 526 + if (prev_sync && jiffies - prev_sync < 20 * HZ) 527 + return; 528 + 529 + prev_sync = jiffies; 530 + get_monotonic_boottime(&ts); 531 + usec = (timespec_to_ns(&ts)) / NSEC_PER_USEC; 532 + ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t)); 533 + } 534 + 535 + /** 536 + * recv_ipc() - Receive and process IPC management messages 537 + * @dev: ishtp device instance 538 + * @doorbell_val: doorbell value 539 + * 540 + * This function runs in ISR context. 541 + * NOTE: Any other mng command than reset_notify and reset_notify_ack 542 + * won't wake BH handler 543 + */ 544 + static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val) 545 + { 546 + uint32_t mng_cmd; 547 + 548 + mng_cmd = IPC_HEADER_GET_MNG_CMD(doorbell_val); 549 + 550 + switch (mng_cmd) { 551 + default: 552 + break; 553 + 554 + case MNG_RX_CMPL_INDICATION: 555 + if (dev->suspend_flag) { 556 + dev->suspend_flag = 0; 557 + wake_up_interruptible(&dev->suspend_wait); 558 + } 559 + if (dev->resume_flag) { 560 + dev->resume_flag = 0; 561 + wake_up_interruptible(&dev->resume_wait); 562 + } 563 + 564 + write_ipc_from_queue(dev); 565 + break; 566 + 567 + case MNG_RESET_NOTIFY: 568 + if (!ishtp_dev) { 569 + ishtp_dev = dev; 570 + INIT_WORK(&fw_reset_work, fw_reset_work_fn); 571 + } 572 + schedule_work(&fw_reset_work); 573 + break; 574 + 575 + case MNG_RESET_NOTIFY_ACK: 576 + dev->recvd_hw_ready = 1; 577 + wake_up_interruptible(&dev->wait_hw_ready); 578 + break; 579 + } 580 + } 581 + 582 + /** 583 + * ish_irq_handler() - ISH IRQ handler 584 + * @irq: irq number 585 + * @dev_id: ishtp device pointer 586 + * 587 + * ISH IRQ handler. If interrupt is generated and is for ISH it will process 588 + * the interrupt. 589 + */ 590 + irqreturn_t ish_irq_handler(int irq, void *dev_id) 591 + { 592 + struct ishtp_device *dev = dev_id; 593 + uint32_t doorbell_val; 594 + bool interrupt_generated; 595 + 596 + /* Check that it's interrupt from ISH (may be shared) */ 597 + interrupt_generated = check_generated_interrupt(dev); 598 + 599 + if (!interrupt_generated) 600 + return IRQ_NONE; 601 + 602 + doorbell_val = ish_reg_read(dev, IPC_REG_ISH2HOST_DRBL); 603 + if (!IPC_IS_BUSY(doorbell_val)) 604 + return IRQ_HANDLED; 605 + 606 + if (dev->dev_state == ISHTP_DEV_DISABLED) 607 + return IRQ_HANDLED; 608 + 609 + /* Sanity check: IPC dgram length in header */ 610 + if (IPC_HEADER_GET_LENGTH(doorbell_val) > IPC_PAYLOAD_SIZE) { 611 + dev_err(dev->devc, 612 + "IPC hdr - bad length: %u; dropped\n", 613 + (unsigned int)IPC_HEADER_GET_LENGTH(doorbell_val)); 614 + goto eoi; 615 + } 616 + 617 + switch (IPC_HEADER_GET_PROTOCOL(doorbell_val)) { 618 + default: 619 + break; 620 + case IPC_PROTOCOL_MNG: 621 + recv_ipc(dev, doorbell_val); 622 + break; 623 + case IPC_PROTOCOL_ISHTP: 624 + ishtp_recv(dev); 625 + break; 626 + } 627 + 628 + eoi: 629 + /* Update IPC counters */ 630 + ++dev->ipc_rx_cnt; 631 + dev->ipc_rx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); 632 + 633 + ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0); 634 + /* Flush write to doorbell */ 635 + ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 636 + 637 + return IRQ_HANDLED; 638 + } 639 + 640 + /** 641 + * _ish_hw_reset() - HW reset 642 + * @dev: ishtp device pointer 643 + * 644 + * Reset ISH HW to recover if any error 645 + * 646 + * Return: 0 for success else error fault code 647 + */ 648 + static int _ish_hw_reset(struct ishtp_device *dev) 649 + { 650 + struct pci_dev *pdev = dev->pdev; 651 + int rv; 652 + unsigned int dma_delay; 653 + uint16_t csr; 654 + 655 + if (!pdev) 656 + return -ENODEV; 657 + 658 + rv = pci_reset_function(pdev); 659 + if (!rv) 660 + dev->dev_state = ISHTP_DEV_RESETTING; 661 + 662 + if (!pdev->pm_cap) { 663 + dev_err(&pdev->dev, "Can't reset - no PM caps\n"); 664 + return -EINVAL; 665 + } 666 + 667 + /* Now trigger reset to FW */ 668 + ish_reg_write(dev, IPC_REG_ISH_RMP2, 0); 669 + 670 + for (dma_delay = 0; dma_delay < MAX_DMA_DELAY && 671 + _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA); 672 + dma_delay += 5) 673 + mdelay(5); 674 + 675 + if (dma_delay >= MAX_DMA_DELAY) { 676 + dev_err(&pdev->dev, 677 + "Can't reset - stuck with DMA in-progress\n"); 678 + return -EBUSY; 679 + } 680 + 681 + pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &csr); 682 + 683 + csr &= ~PCI_PM_CTRL_STATE_MASK; 684 + csr |= PCI_D3hot; 685 + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); 686 + 687 + mdelay(pdev->d3_delay); 688 + 689 + csr &= ~PCI_PM_CTRL_STATE_MASK; 690 + csr |= PCI_D0; 691 + pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); 692 + 693 + ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); 694 + 695 + /* 696 + * Send 0 IPC message so that ISH FW wakes up if it was already 697 + * asleep 698 + */ 699 + ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); 700 + 701 + /* Flush writes to doorbell and REMAP2 */ 702 + ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 703 + 704 + return 0; 705 + } 706 + 707 + /** 708 + * _ish_ipc_reset() - IPC reset 709 + * @dev: ishtp device pointer 710 + * 711 + * Resets host and fw IPC and upper layers 712 + * 713 + * Return: 0 for success else error fault code 714 + */ 715 + static int _ish_ipc_reset(struct ishtp_device *dev) 716 + { 717 + struct ipc_rst_payload_type ipc_mng_msg; 718 + int rv = 0; 719 + 720 + ipc_mng_msg.reset_id = 1; 721 + ipc_mng_msg.reserved = 0; 722 + 723 + set_host_ready(dev); 724 + 725 + /* Clear the incoming doorbell */ 726 + ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0); 727 + /* Flush write to doorbell */ 728 + ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 729 + 730 + dev->recvd_hw_ready = 0; 731 + 732 + /* send message */ 733 + rv = ipc_send_mng_msg(dev, MNG_RESET_NOTIFY, &ipc_mng_msg, 734 + sizeof(struct ipc_rst_payload_type)); 735 + if (rv) { 736 + dev_err(dev->devc, "Failed to send IPC MNG_RESET_NOTIFY\n"); 737 + return rv; 738 + } 739 + 740 + wait_event_interruptible_timeout(dev->wait_hw_ready, 741 + dev->recvd_hw_ready, 2 * HZ); 742 + if (!dev->recvd_hw_ready) { 743 + dev_err(dev->devc, "Timed out waiting for HW ready\n"); 744 + rv = -ENODEV; 745 + } 746 + 747 + return rv; 748 + } 749 + 750 + /** 751 + * ish_hw_start() -Start ISH HW 752 + * @dev: ishtp device pointer 753 + * 754 + * Set host to ready state and wait for FW reset 755 + * 756 + * Return: 0 for success else error fault code 757 + */ 758 + int ish_hw_start(struct ishtp_device *dev) 759 + { 760 + ish_set_host_rdy(dev); 761 + /* After that we can enable ISH DMA operation */ 762 + ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); 763 + 764 + /* 765 + * Send 0 IPC message so that ISH FW wakes up if it was already 766 + * asleep 767 + */ 768 + ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); 769 + /* Flush write to doorbell */ 770 + ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 771 + 772 + set_host_ready(dev); 773 + 774 + /* wait for FW-initiated reset flow */ 775 + if (!dev->recvd_hw_ready) 776 + wait_event_interruptible_timeout(dev->wait_hw_ready, 777 + dev->recvd_hw_ready, 778 + 10 * HZ); 779 + 780 + if (!dev->recvd_hw_ready) { 781 + dev_err(dev->devc, 782 + "[ishtp-ish]: Timed out waiting for FW-initiated reset\n"); 783 + return -ENODEV; 784 + } 785 + 786 + return 0; 787 + } 788 + 789 + /** 790 + * ish_ipc_get_header() -Get doorbell value 791 + * @dev: ishtp device pointer 792 + * @length: length of message 793 + * @busy: busy status 794 + * 795 + * Get door bell value from message header 796 + * 797 + * Return: door bell value 798 + */ 799 + static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length, 800 + int busy) 801 + { 802 + uint32_t drbl_val; 803 + 804 + drbl_val = IPC_BUILD_HEADER(length, IPC_PROTOCOL_ISHTP, busy); 805 + 806 + return drbl_val; 807 + } 808 + 809 + static const struct ishtp_hw_ops ish_hw_ops = { 810 + .hw_reset = _ish_hw_reset, 811 + .ipc_reset = _ish_ipc_reset, 812 + .ipc_get_header = ish_ipc_get_header, 813 + .ishtp_read = _ishtp_read, 814 + .write = write_ipc_to_queue, 815 + .get_fw_status = _ish_read_fw_sts_reg, 816 + .sync_fw_clock = _ish_sync_fw_clock, 817 + .ishtp_read_hdr = _ishtp_read_hdr 818 + }; 819 + 820 + /** 821 + * ish_dev_init() -Initialize ISH devoce 822 + * @pdev: PCI device 823 + * 824 + * Allocate ISHTP device and initialize IPC processing 825 + * 826 + * Return: ISHTP device instance on success else NULL 827 + */ 828 + struct ishtp_device *ish_dev_init(struct pci_dev *pdev) 829 + { 830 + struct ishtp_device *dev; 831 + int i; 832 + 833 + dev = kzalloc(sizeof(struct ishtp_device) + sizeof(struct ish_hw), 834 + GFP_KERNEL); 835 + if (!dev) 836 + return NULL; 837 + 838 + ishtp_device_init(dev); 839 + 840 + init_waitqueue_head(&dev->wait_hw_ready); 841 + 842 + spin_lock_init(&dev->wr_processing_spinlock); 843 + spin_lock_init(&dev->out_ipc_spinlock); 844 + 845 + /* Init IPC processing and free lists */ 846 + INIT_LIST_HEAD(&dev->wr_processing_list_head.link); 847 + INIT_LIST_HEAD(&dev->wr_free_list_head.link); 848 + for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { 849 + struct wr_msg_ctl_info *tx_buf; 850 + 851 + tx_buf = kzalloc(sizeof(struct wr_msg_ctl_info), GFP_KERNEL); 852 + if (!tx_buf) { 853 + /* 854 + * IPC buffers may be limited or not available 855 + * at all - although this shouldn't happen 856 + */ 857 + dev_err(dev->devc, 858 + "[ishtp-ish]: failure in Tx FIFO allocations (%d)\n", 859 + i); 860 + break; 861 + } 862 + list_add_tail(&tx_buf->link, &dev->wr_free_list_head.link); 863 + } 864 + 865 + dev->ops = &ish_hw_ops; 866 + dev->devc = &pdev->dev; 867 + dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr); 868 + return dev; 869 + } 870 + 871 + /** 872 + * ish_device_disable() - Disable ISH device 873 + * @dev: ISHTP device pointer 874 + * 875 + * Disable ISH by clearing host ready to inform firmware. 876 + */ 877 + void ish_device_disable(struct ishtp_device *dev) 878 + { 879 + dev->dev_state = ISHTP_DEV_DISABLED; 880 + ish_clr_host_rdy(dev); 881 + }
+322
drivers/hid/intel-ish-hid/ipc/pci-ish.c
··· 1 + /* 2 + * PCI glue for ISHTP provider device (ISH) driver 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include <linux/module.h> 17 + #include <linux/moduleparam.h> 18 + #include <linux/kernel.h> 19 + #include <linux/device.h> 20 + #include <linux/fs.h> 21 + #include <linux/errno.h> 22 + #include <linux/types.h> 23 + #include <linux/pci.h> 24 + #include <linux/sched.h> 25 + #include <linux/interrupt.h> 26 + #include <linux/workqueue.h> 27 + #include <linux/miscdevice.h> 28 + #define CREATE_TRACE_POINTS 29 + #include <trace/events/intel_ish.h> 30 + #include "ishtp-dev.h" 31 + #include "hw-ish.h" 32 + 33 + static const struct pci_device_id ish_pci_tbl[] = { 34 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CHV_DEVICE_ID)}, 35 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Ax_DEVICE_ID)}, 36 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, BXT_Bx_DEVICE_ID)}, 37 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, APL_Ax_DEVICE_ID)}, 38 + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_Ax_DEVICE_ID)}, 39 + {0, } 40 + }; 41 + MODULE_DEVICE_TABLE(pci, ish_pci_tbl); 42 + 43 + /** 44 + * ish_event_tracer() - Callback function to dump trace messages 45 + * @dev: ishtp device 46 + * @format: printf style format 47 + * 48 + * Callback to direct log messages to Linux trace buffers 49 + */ 50 + static void ish_event_tracer(struct ishtp_device *dev, char *format, ...) 51 + { 52 + if (trace_ishtp_dump_enabled()) { 53 + va_list args; 54 + char tmp_buf[100]; 55 + 56 + va_start(args, format); 57 + vsnprintf(tmp_buf, sizeof(tmp_buf), format, args); 58 + va_end(args); 59 + 60 + trace_ishtp_dump(tmp_buf); 61 + } 62 + } 63 + 64 + /** 65 + * ish_init() - Init function 66 + * @dev: ishtp device 67 + * 68 + * This function initialize wait queues for suspend/resume and call 69 + * calls hadware initialization function. This will initiate 70 + * startup sequence 71 + * 72 + * Return: 0 for success or error code for failure 73 + */ 74 + static int ish_init(struct ishtp_device *dev) 75 + { 76 + int ret; 77 + 78 + /* Set the state of ISH HW to start */ 79 + ret = ish_hw_start(dev); 80 + if (ret) { 81 + dev_err(dev->devc, "ISH: hw start failed.\n"); 82 + return ret; 83 + } 84 + 85 + /* Start the inter process communication to ISH processor */ 86 + ret = ishtp_start(dev); 87 + if (ret) { 88 + dev_err(dev->devc, "ISHTP: Protocol init failed.\n"); 89 + return ret; 90 + } 91 + 92 + return 0; 93 + } 94 + 95 + /** 96 + * ish_probe() - PCI driver probe callback 97 + * @pdev: pci device 98 + * @ent: pci device id 99 + * 100 + * Initialize PCI function, setup interrupt and call for ISH initialization 101 + * 102 + * Return: 0 for success or error code for failure 103 + */ 104 + static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 105 + { 106 + struct ishtp_device *dev; 107 + struct ish_hw *hw; 108 + int ret; 109 + 110 + /* enable pci dev */ 111 + ret = pci_enable_device(pdev); 112 + if (ret) { 113 + dev_err(&pdev->dev, "ISH: Failed to enable PCI device\n"); 114 + return ret; 115 + } 116 + 117 + /* set PCI host mastering */ 118 + pci_set_master(pdev); 119 + 120 + /* pci request regions for ISH driver */ 121 + ret = pci_request_regions(pdev, KBUILD_MODNAME); 122 + if (ret) { 123 + dev_err(&pdev->dev, "ISH: Failed to get PCI regions\n"); 124 + goto disable_device; 125 + } 126 + 127 + /* allocates and initializes the ISH dev structure */ 128 + dev = ish_dev_init(pdev); 129 + if (!dev) { 130 + ret = -ENOMEM; 131 + goto release_regions; 132 + } 133 + hw = to_ish_hw(dev); 134 + dev->print_log = ish_event_tracer; 135 + 136 + /* mapping IO device memory */ 137 + hw->mem_addr = pci_iomap(pdev, 0, 0); 138 + if (!hw->mem_addr) { 139 + dev_err(&pdev->dev, "ISH: mapping I/O range failure\n"); 140 + ret = -ENOMEM; 141 + goto free_device; 142 + } 143 + 144 + dev->pdev = pdev; 145 + 146 + pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3; 147 + 148 + /* request and enable interrupt */ 149 + ret = request_irq(pdev->irq, ish_irq_handler, IRQF_NO_SUSPEND, 150 + KBUILD_MODNAME, dev); 151 + if (ret) { 152 + dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n", 153 + pdev->irq); 154 + goto free_device; 155 + } 156 + 157 + dev_set_drvdata(dev->devc, dev); 158 + 159 + init_waitqueue_head(&dev->suspend_wait); 160 + init_waitqueue_head(&dev->resume_wait); 161 + 162 + ret = ish_init(dev); 163 + if (ret) 164 + goto free_irq; 165 + 166 + return 0; 167 + 168 + free_irq: 169 + free_irq(pdev->irq, dev); 170 + free_device: 171 + pci_iounmap(pdev, hw->mem_addr); 172 + kfree(dev); 173 + release_regions: 174 + pci_release_regions(pdev); 175 + disable_device: 176 + pci_clear_master(pdev); 177 + pci_disable_device(pdev); 178 + dev_err(&pdev->dev, "ISH: PCI driver initialization failed.\n"); 179 + 180 + return ret; 181 + } 182 + 183 + /** 184 + * ish_remove() - PCI driver remove callback 185 + * @pdev: pci device 186 + * 187 + * This function does cleanup of ISH on pci remove callback 188 + */ 189 + static void ish_remove(struct pci_dev *pdev) 190 + { 191 + struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev); 192 + struct ish_hw *hw = to_ish_hw(ishtp_dev); 193 + 194 + ishtp_bus_remove_all_clients(ishtp_dev, false); 195 + ish_device_disable(ishtp_dev); 196 + 197 + free_irq(pdev->irq, ishtp_dev); 198 + pci_iounmap(pdev, hw->mem_addr); 199 + pci_release_regions(pdev); 200 + pci_clear_master(pdev); 201 + pci_disable_device(pdev); 202 + kfree(ishtp_dev); 203 + } 204 + 205 + static struct device *ish_resume_device; 206 + 207 + /** 208 + * ish_resume_handler() - Work function to complete resume 209 + * @work: work struct 210 + * 211 + * The resume work function to complete resume function asynchronously. 212 + * There are two types of platforms, one where ISH is not powered off, 213 + * in that case a simple resume message is enough, others we need 214 + * a reset sequence. 215 + */ 216 + static void ish_resume_handler(struct work_struct *work) 217 + { 218 + struct pci_dev *pdev = to_pci_dev(ish_resume_device); 219 + struct ishtp_device *dev = pci_get_drvdata(pdev); 220 + int ret; 221 + 222 + ishtp_send_resume(dev); 223 + 224 + /* 50 ms to get resume response */ 225 + if (dev->resume_flag) 226 + ret = wait_event_interruptible_timeout(dev->resume_wait, 227 + !dev->resume_flag, 228 + msecs_to_jiffies(50)); 229 + 230 + /* 231 + * If no resume response. This platform is not S0ix compatible 232 + * So on resume full reboot of ISH processor will happen, so 233 + * need to go through init sequence again 234 + */ 235 + if (dev->resume_flag) 236 + ish_init(dev); 237 + } 238 + 239 + /** 240 + * ish_suspend() - ISH suspend callback 241 + * @device: device pointer 242 + * 243 + * ISH suspend callback 244 + * 245 + * Return: 0 to the pm core 246 + */ 247 + static int ish_suspend(struct device *device) 248 + { 249 + struct pci_dev *pdev = to_pci_dev(device); 250 + struct ishtp_device *dev = pci_get_drvdata(pdev); 251 + 252 + enable_irq_wake(pdev->irq); 253 + /* 254 + * If previous suspend hasn't been asnwered then ISH is likely dead, 255 + * don't attempt nested notification 256 + */ 257 + if (dev->suspend_flag) 258 + return 0; 259 + 260 + dev->resume_flag = 0; 261 + dev->suspend_flag = 1; 262 + ishtp_send_suspend(dev); 263 + 264 + /* 25 ms should be enough for live ISH to flush all IPC buf */ 265 + if (dev->suspend_flag) 266 + wait_event_interruptible_timeout(dev->suspend_wait, 267 + !dev->suspend_flag, 268 + msecs_to_jiffies(25)); 269 + 270 + return 0; 271 + } 272 + 273 + static DECLARE_WORK(resume_work, ish_resume_handler); 274 + /** 275 + * ish_resume() - ISH resume callback 276 + * @device: device pointer 277 + * 278 + * ISH resume callback 279 + * 280 + * Return: 0 to the pm core 281 + */ 282 + static int ish_resume(struct device *device) 283 + { 284 + struct pci_dev *pdev = to_pci_dev(device); 285 + struct ishtp_device *dev = pci_get_drvdata(pdev); 286 + 287 + ish_resume_device = device; 288 + dev->resume_flag = 1; 289 + 290 + disable_irq_wake(pdev->irq); 291 + schedule_work(&resume_work); 292 + 293 + return 0; 294 + } 295 + 296 + #ifdef CONFIG_PM 297 + static const struct dev_pm_ops ish_pm_ops = { 298 + .suspend = ish_suspend, 299 + .resume = ish_resume, 300 + }; 301 + #define ISHTP_ISH_PM_OPS (&ish_pm_ops) 302 + #else 303 + #define ISHTP_ISH_PM_OPS NULL 304 + #endif 305 + 306 + static struct pci_driver ish_driver = { 307 + .name = KBUILD_MODNAME, 308 + .id_table = ish_pci_tbl, 309 + .probe = ish_probe, 310 + .remove = ish_remove, 311 + .driver.pm = ISHTP_ISH_PM_OPS, 312 + }; 313 + 314 + module_pci_driver(ish_driver); 315 + 316 + /* Original author */ 317 + MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>"); 318 + /* Adoption to upstream Linux kernel */ 319 + MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 320 + 321 + MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver"); 322 + MODULE_LICENSE("GPL");
+64
drivers/hid/intel-ish-hid/ipc/utils.h
··· 1 + /* 2 + * Utility macros of ISH 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + #ifndef UTILS__H 16 + #define UTILS__H 17 + 18 + #define WAIT_FOR_SEND_SLICE (HZ / 10) 19 + #define WAIT_FOR_CONNECT_SLICE (HZ / 10) 20 + 21 + /* 22 + * Waits for specified event when a thread that triggers event can't signal 23 + * Also, waits *at_least* `timeinc` after condition is satisfied 24 + */ 25 + #define timed_wait_for(timeinc, condition) \ 26 + do { \ 27 + int completed = 0; \ 28 + do { \ 29 + unsigned long j; \ 30 + int done = 0; \ 31 + \ 32 + completed = (condition); \ 33 + for (j = jiffies, done = 0; !done; ) { \ 34 + schedule_timeout(timeinc); \ 35 + if (time_is_before_eq_jiffies(j + timeinc)) \ 36 + done = 1; \ 37 + } \ 38 + } while (!(completed)); \ 39 + } while (0) 40 + 41 + 42 + /* 43 + * Waits for specified event when a thread that triggers event 44 + * can't signal with timeout (use whenever we may hang) 45 + */ 46 + #define timed_wait_for_timeout(timeinc, condition, timeout) \ 47 + do { \ 48 + int t = timeout; \ 49 + do { \ 50 + unsigned long j; \ 51 + int done = 0; \ 52 + \ 53 + for (j = jiffies, done = 0; !done; ) { \ 54 + schedule_timeout(timeinc); \ 55 + if (time_is_before_eq_jiffies(j + timeinc)) \ 56 + done = 1; \ 57 + } \ 58 + t -= timeinc; \ 59 + if (t <= 0) \ 60 + break; \ 61 + } while (!(condition)); \ 62 + } while (0) 63 + 64 + #endif /* UTILS__H */
+978
drivers/hid/intel-ish-hid/ishtp-hid-client.c
··· 1 + /* 2 + * ISHTP client driver for HID (ISH) 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include <linux/module.h> 17 + #include <linux/hid.h> 18 + #include <linux/sched.h> 19 + #include "ishtp/ishtp-dev.h" 20 + #include "ishtp/client.h" 21 + #include "ishtp-hid.h" 22 + 23 + /* Rx ring buffer pool size */ 24 + #define HID_CL_RX_RING_SIZE 32 25 + #define HID_CL_TX_RING_SIZE 16 26 + 27 + /** 28 + * report_bad_packets() - Report bad packets 29 + * @hid_ishtp_cl: Client instance to get stats 30 + * @recv_buf: Raw received host interface message 31 + * @cur_pos: Current position index in payload 32 + * @payload_len: Length of payload expected 33 + * 34 + * Dumps error in case bad packet is received 35 + */ 36 + static void report_bad_packet(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, 37 + size_t cur_pos, size_t payload_len) 38 + { 39 + struct hostif_msg *recv_msg = recv_buf; 40 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 41 + 42 + dev_err(&client_data->cl_device->dev, "[hid-ish]: BAD packet %02X\n" 43 + "total_bad=%u cur_pos=%u\n" 44 + "[%02X %02X %02X %02X]\n" 45 + "payload_len=%u\n" 46 + "multi_packet_cnt=%u\n" 47 + "is_response=%02X\n", 48 + recv_msg->hdr.command, client_data->bad_recv_cnt, 49 + (unsigned int)cur_pos, 50 + ((unsigned char *)recv_msg)[0], ((unsigned char *)recv_msg)[1], 51 + ((unsigned char *)recv_msg)[2], ((unsigned char *)recv_msg)[3], 52 + (unsigned int)payload_len, client_data->multi_packet_cnt, 53 + recv_msg->hdr.command & ~CMD_MASK); 54 + } 55 + 56 + /** 57 + * process_recv() - Received and parse incoming packet 58 + * @hid_ishtp_cl: Client instance to get stats 59 + * @recv_buf: Raw received host interface message 60 + * @data_len: length of the message 61 + * 62 + * Parse the incoming packet. If it is a response packet then it will update 63 + * per instance flags and wake up the caller waiting to for the response. 64 + */ 65 + static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf, 66 + size_t data_len) 67 + { 68 + struct hostif_msg *recv_msg; 69 + unsigned char *payload; 70 + struct device_info *dev_info; 71 + int i, j; 72 + size_t payload_len, total_len, cur_pos; 73 + int report_type; 74 + struct report_list *reports_list; 75 + char *reports; 76 + size_t report_len; 77 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 78 + int curr_hid_dev = client_data->cur_hid_dev; 79 + 80 + if (data_len < sizeof(struct hostif_msg_hdr)) { 81 + dev_err(&client_data->cl_device->dev, 82 + "[hid-ish]: error, received %u which is less than data header %u\n", 83 + (unsigned int)data_len, 84 + (unsigned int)sizeof(struct hostif_msg_hdr)); 85 + ++client_data->bad_recv_cnt; 86 + ish_hw_reset(hid_ishtp_cl->dev); 87 + return; 88 + } 89 + 90 + payload = recv_buf + sizeof(struct hostif_msg_hdr); 91 + total_len = data_len; 92 + cur_pos = 0; 93 + 94 + do { 95 + recv_msg = (struct hostif_msg *)(recv_buf + cur_pos); 96 + payload_len = recv_msg->hdr.size; 97 + 98 + /* Sanity checks */ 99 + if (cur_pos + payload_len + sizeof(struct hostif_msg) > 100 + total_len) { 101 + ++client_data->bad_recv_cnt; 102 + report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos, 103 + payload_len); 104 + ish_hw_reset(hid_ishtp_cl->dev); 105 + break; 106 + } 107 + 108 + hid_ishtp_trace(client_data, "%s %d\n", 109 + __func__, recv_msg->hdr.command & CMD_MASK); 110 + 111 + switch (recv_msg->hdr.command & CMD_MASK) { 112 + case HOSTIF_DM_ENUM_DEVICES: 113 + if ((!(recv_msg->hdr.command & ~CMD_MASK) || 114 + client_data->init_done)) { 115 + ++client_data->bad_recv_cnt; 116 + report_bad_packet(hid_ishtp_cl, recv_msg, 117 + cur_pos, 118 + payload_len); 119 + ish_hw_reset(hid_ishtp_cl->dev); 120 + break; 121 + } 122 + client_data->hid_dev_count = (unsigned int)*payload; 123 + if (!client_data->hid_devices) 124 + client_data->hid_devices = devm_kzalloc( 125 + &client_data->cl_device->dev, 126 + client_data->hid_dev_count * 127 + sizeof(struct device_info), 128 + GFP_KERNEL); 129 + if (!client_data->hid_devices) { 130 + dev_err(&client_data->cl_device->dev, 131 + "Mem alloc failed for hid device info\n"); 132 + wake_up_interruptible(&client_data->init_wait); 133 + break; 134 + } 135 + for (i = 0; i < client_data->hid_dev_count; ++i) { 136 + if (1 + sizeof(struct device_info) * i >= 137 + payload_len) { 138 + dev_err(&client_data->cl_device->dev, 139 + "[hid-ish]: [ENUM_DEVICES]: content size %lu is bigger than payload_len %u\n", 140 + 1 + sizeof(struct device_info) 141 + * i, 142 + (unsigned int)payload_len); 143 + } 144 + 145 + if (1 + sizeof(struct device_info) * i >= 146 + data_len) 147 + break; 148 + 149 + dev_info = (struct device_info *)(payload + 1 + 150 + sizeof(struct device_info) * i); 151 + if (client_data->hid_devices) 152 + memcpy(client_data->hid_devices + i, 153 + dev_info, 154 + sizeof(struct device_info)); 155 + } 156 + 157 + client_data->enum_devices_done = true; 158 + wake_up_interruptible(&client_data->init_wait); 159 + 160 + break; 161 + 162 + case HOSTIF_GET_HID_DESCRIPTOR: 163 + if ((!(recv_msg->hdr.command & ~CMD_MASK) || 164 + client_data->init_done)) { 165 + ++client_data->bad_recv_cnt; 166 + report_bad_packet(hid_ishtp_cl, recv_msg, 167 + cur_pos, 168 + payload_len); 169 + ish_hw_reset(hid_ishtp_cl->dev); 170 + break; 171 + } 172 + if (!client_data->hid_descr[curr_hid_dev]) 173 + client_data->hid_descr[curr_hid_dev] = 174 + devm_kmalloc(&client_data->cl_device->dev, 175 + payload_len, GFP_KERNEL); 176 + if (client_data->hid_descr[curr_hid_dev]) { 177 + memcpy(client_data->hid_descr[curr_hid_dev], 178 + payload, payload_len); 179 + client_data->hid_descr_size[curr_hid_dev] = 180 + payload_len; 181 + client_data->hid_descr_done = true; 182 + } 183 + wake_up_interruptible(&client_data->init_wait); 184 + 185 + break; 186 + 187 + case HOSTIF_GET_REPORT_DESCRIPTOR: 188 + if ((!(recv_msg->hdr.command & ~CMD_MASK) || 189 + client_data->init_done)) { 190 + ++client_data->bad_recv_cnt; 191 + report_bad_packet(hid_ishtp_cl, recv_msg, 192 + cur_pos, 193 + payload_len); 194 + ish_hw_reset(hid_ishtp_cl->dev); 195 + break; 196 + } 197 + if (!client_data->report_descr[curr_hid_dev]) 198 + client_data->report_descr[curr_hid_dev] = 199 + devm_kmalloc(&client_data->cl_device->dev, 200 + payload_len, GFP_KERNEL); 201 + if (client_data->report_descr[curr_hid_dev]) { 202 + memcpy(client_data->report_descr[curr_hid_dev], 203 + payload, 204 + payload_len); 205 + client_data->report_descr_size[curr_hid_dev] = 206 + payload_len; 207 + client_data->report_descr_done = true; 208 + } 209 + wake_up_interruptible(&client_data->init_wait); 210 + 211 + break; 212 + 213 + case HOSTIF_GET_FEATURE_REPORT: 214 + report_type = HID_FEATURE_REPORT; 215 + goto do_get_report; 216 + 217 + case HOSTIF_GET_INPUT_REPORT: 218 + report_type = HID_INPUT_REPORT; 219 + do_get_report: 220 + /* Get index of device that matches this id */ 221 + for (i = 0; i < client_data->num_hid_devices; ++i) { 222 + if (recv_msg->hdr.device_id == 223 + client_data->hid_devices[i].dev_id) 224 + if (client_data->hid_sensor_hubs[i]) { 225 + hid_input_report( 226 + client_data->hid_sensor_hubs[ 227 + i], 228 + report_type, payload, 229 + payload_len, 0); 230 + ishtp_hid_wakeup( 231 + client_data->hid_sensor_hubs[ 232 + i]); 233 + break; 234 + } 235 + } 236 + break; 237 + 238 + case HOSTIF_SET_FEATURE_REPORT: 239 + /* Get index of device that matches this id */ 240 + for (i = 0; i < client_data->num_hid_devices; ++i) { 241 + if (recv_msg->hdr.device_id == 242 + client_data->hid_devices[i].dev_id) 243 + if (client_data->hid_sensor_hubs[i]) { 244 + ishtp_hid_wakeup( 245 + client_data->hid_sensor_hubs[ 246 + i]); 247 + break; 248 + } 249 + } 250 + break; 251 + 252 + case HOSTIF_PUBLISH_INPUT_REPORT: 253 + report_type = HID_INPUT_REPORT; 254 + for (i = 0; i < client_data->num_hid_devices; ++i) 255 + if (recv_msg->hdr.device_id == 256 + client_data->hid_devices[i].dev_id) 257 + if (client_data->hid_sensor_hubs[i]) 258 + hid_input_report( 259 + client_data->hid_sensor_hubs[ 260 + i], 261 + report_type, payload, 262 + payload_len, 0); 263 + break; 264 + 265 + case HOSTIF_PUBLISH_INPUT_REPORT_LIST: 266 + report_type = HID_INPUT_REPORT; 267 + reports_list = (struct report_list *)payload; 268 + reports = (char *)reports_list->reports; 269 + 270 + for (j = 0; j < reports_list->num_of_reports; j++) { 271 + recv_msg = (struct hostif_msg *)(reports + 272 + sizeof(uint16_t)); 273 + report_len = *(uint16_t *)reports; 274 + payload = reports + sizeof(uint16_t) + 275 + sizeof(struct hostif_msg_hdr); 276 + payload_len = report_len - 277 + sizeof(struct hostif_msg_hdr); 278 + 279 + for (i = 0; i < client_data->num_hid_devices; 280 + ++i) 281 + if (recv_msg->hdr.device_id == 282 + client_data->hid_devices[i].dev_id && 283 + client_data->hid_sensor_hubs[i]) { 284 + hid_input_report( 285 + client_data->hid_sensor_hubs[ 286 + i], 287 + report_type, 288 + payload, payload_len, 289 + 0); 290 + } 291 + 292 + reports += sizeof(uint16_t) + report_len; 293 + } 294 + break; 295 + default: 296 + ++client_data->bad_recv_cnt; 297 + report_bad_packet(hid_ishtp_cl, recv_msg, cur_pos, 298 + payload_len); 299 + ish_hw_reset(hid_ishtp_cl->dev); 300 + break; 301 + 302 + } 303 + 304 + if (!cur_pos && cur_pos + payload_len + 305 + sizeof(struct hostif_msg) < total_len) 306 + ++client_data->multi_packet_cnt; 307 + 308 + cur_pos += payload_len + sizeof(struct hostif_msg); 309 + payload += payload_len + sizeof(struct hostif_msg); 310 + 311 + } while (cur_pos < total_len); 312 + } 313 + 314 + /** 315 + * ish_cl_event_cb() - bus driver callback for incoming message/packet 316 + * @device: Pointer to the the ishtp client device for which this message 317 + * is targeted 318 + * 319 + * Remove the packet from the list and process the message by calling 320 + * process_recv 321 + */ 322 + static void ish_cl_event_cb(struct ishtp_cl_device *device) 323 + { 324 + struct ishtp_cl *hid_ishtp_cl = device->driver_data; 325 + struct ishtp_cl_rb *rb_in_proc; 326 + size_t r_length; 327 + unsigned long flags; 328 + 329 + if (!hid_ishtp_cl) 330 + return; 331 + 332 + spin_lock_irqsave(&hid_ishtp_cl->in_process_spinlock, flags); 333 + while (!list_empty(&hid_ishtp_cl->in_process_list.list)) { 334 + rb_in_proc = list_entry( 335 + hid_ishtp_cl->in_process_list.list.next, 336 + struct ishtp_cl_rb, list); 337 + list_del_init(&rb_in_proc->list); 338 + spin_unlock_irqrestore(&hid_ishtp_cl->in_process_spinlock, 339 + flags); 340 + 341 + if (!rb_in_proc->buffer.data) 342 + return; 343 + 344 + r_length = rb_in_proc->buf_idx; 345 + 346 + /* decide what to do with received data */ 347 + process_recv(hid_ishtp_cl, rb_in_proc->buffer.data, r_length); 348 + 349 + ishtp_cl_io_rb_recycle(rb_in_proc); 350 + spin_lock_irqsave(&hid_ishtp_cl->in_process_spinlock, flags); 351 + } 352 + spin_unlock_irqrestore(&hid_ishtp_cl->in_process_spinlock, flags); 353 + } 354 + 355 + /** 356 + * hid_ishtp_set_feature() - send request to ISH FW to set a feature request 357 + * @hid: hid device instance for this request 358 + * @buf: feature buffer 359 + * @len: Length of feature buffer 360 + * @report_id: Report id for the feature set request 361 + * 362 + * This is called from hid core .request() callback. This function doesn't wait 363 + * for response. 364 + */ 365 + void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len, 366 + int report_id) 367 + { 368 + struct ishtp_hid_data *hid_data = hid->driver_data; 369 + struct ishtp_cl_data *client_data = hid_data->client_data; 370 + struct hostif_msg *msg = (struct hostif_msg *)buf; 371 + int rv; 372 + int i; 373 + 374 + hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid); 375 + 376 + rv = ishtp_hid_link_ready_wait(client_data); 377 + if (rv) { 378 + hid_ishtp_trace(client_data, "%s hid %p link not ready\n", 379 + __func__, hid); 380 + return; 381 + } 382 + 383 + memset(msg, 0, sizeof(struct hostif_msg)); 384 + msg->hdr.command = HOSTIF_SET_FEATURE_REPORT; 385 + for (i = 0; i < client_data->num_hid_devices; ++i) { 386 + if (hid == client_data->hid_sensor_hubs[i]) { 387 + msg->hdr.device_id = 388 + client_data->hid_devices[i].dev_id; 389 + break; 390 + } 391 + } 392 + 393 + if (i == client_data->num_hid_devices) 394 + return; 395 + 396 + rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len); 397 + if (rv) 398 + hid_ishtp_trace(client_data, "%s hid %p send failed\n", 399 + __func__, hid); 400 + } 401 + 402 + /** 403 + * hid_ishtp_get_report() - request to get feature/input report 404 + * @hid: hid device instance for this request 405 + * @report_id: Report id for the get request 406 + * @report_type: Report type for the this request 407 + * 408 + * This is called from hid core .request() callback. This function will send 409 + * request to FW and return without waiting for response. 410 + */ 411 + void hid_ishtp_get_report(struct hid_device *hid, int report_id, 412 + int report_type) 413 + { 414 + struct ishtp_hid_data *hid_data = hid->driver_data; 415 + struct ishtp_cl_data *client_data = hid_data->client_data; 416 + static unsigned char buf[10]; 417 + unsigned int len; 418 + struct hostif_msg_to_sensor *msg = (struct hostif_msg_to_sensor *)buf; 419 + int rv; 420 + int i; 421 + 422 + hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid); 423 + rv = ishtp_hid_link_ready_wait(client_data); 424 + if (rv) { 425 + hid_ishtp_trace(client_data, "%s hid %p link not ready\n", 426 + __func__, hid); 427 + return; 428 + } 429 + 430 + len = sizeof(struct hostif_msg_to_sensor); 431 + 432 + memset(msg, 0, sizeof(struct hostif_msg_to_sensor)); 433 + msg->hdr.command = (report_type == HID_FEATURE_REPORT) ? 434 + HOSTIF_GET_FEATURE_REPORT : HOSTIF_GET_INPUT_REPORT; 435 + for (i = 0; i < client_data->num_hid_devices; ++i) { 436 + if (hid == client_data->hid_sensor_hubs[i]) { 437 + msg->hdr.device_id = 438 + client_data->hid_devices[i].dev_id; 439 + break; 440 + } 441 + } 442 + 443 + if (i == client_data->num_hid_devices) 444 + return; 445 + 446 + msg->report_id = report_id; 447 + rv = ishtp_cl_send(client_data->hid_ishtp_cl, buf, len); 448 + if (rv) 449 + hid_ishtp_trace(client_data, "%s hid %p send failed\n", 450 + __func__, hid); 451 + } 452 + 453 + /** 454 + * ishtp_hid_link_ready_wait() - Wait for link ready 455 + * @client_data: client data instance 456 + * 457 + * If the transport link started suspend process, then wait, till either 458 + * resumed or timeout 459 + * 460 + * Return: 0 on success, non zero on error 461 + */ 462 + int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data) 463 + { 464 + int rc; 465 + 466 + if (client_data->suspended) { 467 + hid_ishtp_trace(client_data, "wait for link ready\n"); 468 + rc = wait_event_interruptible_timeout( 469 + client_data->ishtp_resume_wait, 470 + !client_data->suspended, 471 + 5 * HZ); 472 + 473 + if (rc == 0) { 474 + hid_ishtp_trace(client_data, "link not ready\n"); 475 + return -EIO; 476 + } 477 + hid_ishtp_trace(client_data, "link ready\n"); 478 + } 479 + 480 + return 0; 481 + } 482 + 483 + /** 484 + * ishtp_enum_enum_devices() - Enumerate hid devices 485 + * @hid_ishtp_cl: client instance 486 + * 487 + * Helper function to send request to firmware to enumerate HID devices 488 + * 489 + * Return: 0 on success, non zero on error 490 + */ 491 + static int ishtp_enum_enum_devices(struct ishtp_cl *hid_ishtp_cl) 492 + { 493 + struct hostif_msg msg; 494 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 495 + int retry_count; 496 + int rv; 497 + 498 + /* Send HOSTIF_DM_ENUM_DEVICES */ 499 + memset(&msg, 0, sizeof(struct hostif_msg)); 500 + msg.hdr.command = HOSTIF_DM_ENUM_DEVICES; 501 + rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *)&msg, 502 + sizeof(struct hostif_msg)); 503 + if (rv) 504 + return rv; 505 + 506 + retry_count = 0; 507 + while (!client_data->enum_devices_done && 508 + retry_count < 10) { 509 + wait_event_interruptible_timeout(client_data->init_wait, 510 + client_data->enum_devices_done, 511 + 3 * HZ); 512 + ++retry_count; 513 + if (!client_data->enum_devices_done) 514 + /* Send HOSTIF_DM_ENUM_DEVICES */ 515 + rv = ishtp_cl_send(hid_ishtp_cl, 516 + (unsigned char *) &msg, 517 + sizeof(struct hostif_msg)); 518 + } 519 + if (!client_data->enum_devices_done) { 520 + dev_err(&client_data->cl_device->dev, 521 + "[hid-ish]: timed out waiting for enum_devices\n"); 522 + return -ETIMEDOUT; 523 + } 524 + if (!client_data->hid_devices) { 525 + dev_err(&client_data->cl_device->dev, 526 + "[hid-ish]: failed to allocate HID dev structures\n"); 527 + return -ENOMEM; 528 + } 529 + 530 + client_data->num_hid_devices = client_data->hid_dev_count; 531 + dev_info(&hid_ishtp_cl->device->dev, 532 + "[hid-ish]: enum_devices_done OK, num_hid_devices=%d\n", 533 + client_data->num_hid_devices); 534 + 535 + return 0; 536 + } 537 + 538 + /** 539 + * ishtp_get_hid_descriptor() - Get hid descriptor 540 + * @hid_ishtp_cl: client instance 541 + * @index: Index into the hid_descr array 542 + * 543 + * Helper function to send request to firmware get HID descriptor of a device 544 + * 545 + * Return: 0 on success, non zero on error 546 + */ 547 + static int ishtp_get_hid_descriptor(struct ishtp_cl *hid_ishtp_cl, int index) 548 + { 549 + struct hostif_msg msg; 550 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 551 + int rv; 552 + 553 + /* Get HID descriptor */ 554 + client_data->hid_descr_done = false; 555 + memset(&msg, 0, sizeof(struct hostif_msg)); 556 + msg.hdr.command = HOSTIF_GET_HID_DESCRIPTOR; 557 + msg.hdr.device_id = client_data->hid_devices[index].dev_id; 558 + rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg, 559 + sizeof(struct hostif_msg)); 560 + if (rv) 561 + return rv; 562 + 563 + if (!client_data->hid_descr_done) { 564 + wait_event_interruptible_timeout(client_data->init_wait, 565 + client_data->hid_descr_done, 566 + 3 * HZ); 567 + if (!client_data->hid_descr_done) { 568 + dev_err(&client_data->cl_device->dev, 569 + "[hid-ish]: timed out for hid_descr_done\n"); 570 + return -EIO; 571 + } 572 + 573 + if (!client_data->hid_descr[index]) { 574 + dev_err(&client_data->cl_device->dev, 575 + "[hid-ish]: allocation HID desc fail\n"); 576 + return -ENOMEM; 577 + } 578 + } 579 + 580 + return 0; 581 + } 582 + 583 + /** 584 + * ishtp_get_report_descriptor() - Get report descriptor 585 + * @hid_ishtp_cl: client instance 586 + * @index: Index into the hid_descr array 587 + * 588 + * Helper function to send request to firmware get HID report descriptor of 589 + * a device 590 + * 591 + * Return: 0 on success, non zero on error 592 + */ 593 + static int ishtp_get_report_descriptor(struct ishtp_cl *hid_ishtp_cl, 594 + int index) 595 + { 596 + struct hostif_msg msg; 597 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 598 + int rv; 599 + 600 + /* Get report descriptor */ 601 + client_data->report_descr_done = false; 602 + memset(&msg, 0, sizeof(struct hostif_msg)); 603 + msg.hdr.command = HOSTIF_GET_REPORT_DESCRIPTOR; 604 + msg.hdr.device_id = client_data->hid_devices[index].dev_id; 605 + rv = ishtp_cl_send(hid_ishtp_cl, (unsigned char *) &msg, 606 + sizeof(struct hostif_msg)); 607 + if (rv) 608 + return rv; 609 + 610 + if (!client_data->report_descr_done) 611 + wait_event_interruptible_timeout(client_data->init_wait, 612 + client_data->report_descr_done, 613 + 3 * HZ); 614 + if (!client_data->report_descr_done) { 615 + dev_err(&client_data->cl_device->dev, 616 + "[hid-ish]: timed out for report descr\n"); 617 + return -EIO; 618 + } 619 + if (!client_data->report_descr[index]) { 620 + dev_err(&client_data->cl_device->dev, 621 + "[hid-ish]: failed to alloc report descr\n"); 622 + return -ENOMEM; 623 + } 624 + 625 + return 0; 626 + } 627 + 628 + /** 629 + * hid_ishtp_cl_init() - Init function for ISHTP client 630 + * @hid_ishtp_cl: ISHTP client instance 631 + * @reset: true if called for init after reset 632 + * 633 + * This function complete the initializtion of the client. The summary of 634 + * processing: 635 + * - Send request to enumerate the hid clients 636 + * Get the HID descriptor for each enumearated device 637 + * Get report description of each device 638 + * Register each device wik hid core by calling ishtp_hid_probe 639 + * 640 + * Return: 0 on success, non zero on error 641 + */ 642 + static int hid_ishtp_cl_init(struct ishtp_cl *hid_ishtp_cl, int reset) 643 + { 644 + struct ishtp_device *dev; 645 + unsigned long flags; 646 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 647 + int i; 648 + int rv; 649 + 650 + dev_dbg(&client_data->cl_device->dev, "%s\n", __func__); 651 + hid_ishtp_trace(client_data, "%s reset flag: %d\n", __func__, reset); 652 + 653 + rv = ishtp_cl_link(hid_ishtp_cl, ISHTP_HOST_CLIENT_ID_ANY); 654 + if (rv) { 655 + dev_err(&client_data->cl_device->dev, 656 + "ishtp_cl_link failed\n"); 657 + return -ENOMEM; 658 + } 659 + 660 + client_data->init_done = 0; 661 + 662 + dev = hid_ishtp_cl->dev; 663 + 664 + /* Connect to FW client */ 665 + hid_ishtp_cl->rx_ring_size = HID_CL_RX_RING_SIZE; 666 + hid_ishtp_cl->tx_ring_size = HID_CL_TX_RING_SIZE; 667 + 668 + spin_lock_irqsave(&dev->fw_clients_lock, flags); 669 + i = ishtp_fw_cl_by_uuid(dev, &hid_ishtp_guid); 670 + if (i < 0) { 671 + spin_unlock_irqrestore(&dev->fw_clients_lock, flags); 672 + dev_err(&client_data->cl_device->dev, 673 + "ish client uuid not found\n"); 674 + return i; 675 + } 676 + hid_ishtp_cl->fw_client_id = dev->fw_clients[i].client_id; 677 + spin_unlock_irqrestore(&dev->fw_clients_lock, flags); 678 + hid_ishtp_cl->state = ISHTP_CL_CONNECTING; 679 + 680 + rv = ishtp_cl_connect(hid_ishtp_cl); 681 + if (rv) { 682 + dev_err(&client_data->cl_device->dev, 683 + "client connect fail\n"); 684 + goto err_cl_unlink; 685 + } 686 + 687 + hid_ishtp_trace(client_data, "%s client connected\n", __func__); 688 + 689 + /* Register read callback */ 690 + ishtp_register_event_cb(hid_ishtp_cl->device, ish_cl_event_cb); 691 + 692 + rv = ishtp_enum_enum_devices(hid_ishtp_cl); 693 + if (rv) 694 + goto err_cl_disconnect; 695 + 696 + hid_ishtp_trace(client_data, "%s enumerated device count %d\n", 697 + __func__, client_data->num_hid_devices); 698 + 699 + for (i = 0; i < client_data->num_hid_devices; ++i) { 700 + client_data->cur_hid_dev = i; 701 + 702 + rv = ishtp_get_hid_descriptor(hid_ishtp_cl, i); 703 + if (rv) 704 + goto err_cl_disconnect; 705 + 706 + rv = ishtp_get_report_descriptor(hid_ishtp_cl, i); 707 + if (rv) 708 + goto err_cl_disconnect; 709 + 710 + if (!reset) { 711 + rv = ishtp_hid_probe(i, client_data); 712 + if (rv) { 713 + dev_err(&client_data->cl_device->dev, 714 + "[hid-ish]: HID probe for #%u failed: %d\n", 715 + i, rv); 716 + goto err_cl_disconnect; 717 + } 718 + } 719 + } /* for() on all hid devices */ 720 + 721 + client_data->init_done = 1; 722 + client_data->suspended = false; 723 + wake_up_interruptible(&client_data->ishtp_resume_wait); 724 + hid_ishtp_trace(client_data, "%s successful init\n", __func__); 725 + return 0; 726 + 727 + err_cl_disconnect: 728 + hid_ishtp_cl->state = ISHTP_CL_DISCONNECTING; 729 + ishtp_cl_disconnect(hid_ishtp_cl); 730 + err_cl_unlink: 731 + ishtp_cl_unlink(hid_ishtp_cl); 732 + return rv; 733 + } 734 + 735 + /** 736 + * hid_ishtp_cl_deinit() - Deinit function for ISHTP client 737 + * @hid_ishtp_cl: ISHTP client instance 738 + * 739 + * Unlink and free hid client 740 + */ 741 + static void hid_ishtp_cl_deinit(struct ishtp_cl *hid_ishtp_cl) 742 + { 743 + ishtp_cl_unlink(hid_ishtp_cl); 744 + ishtp_cl_flush_queues(hid_ishtp_cl); 745 + 746 + /* disband and free all Tx and Rx client-level rings */ 747 + ishtp_cl_free(hid_ishtp_cl); 748 + } 749 + 750 + static void hid_ishtp_cl_reset_handler(struct work_struct *work) 751 + { 752 + struct ishtp_cl_data *client_data; 753 + struct ishtp_cl *hid_ishtp_cl; 754 + struct ishtp_cl_device *cl_device; 755 + int retry; 756 + int rv; 757 + 758 + client_data = container_of(work, struct ishtp_cl_data, work); 759 + 760 + hid_ishtp_cl = client_data->hid_ishtp_cl; 761 + cl_device = client_data->cl_device; 762 + 763 + hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__, 764 + hid_ishtp_cl); 765 + dev_dbg(&cl_device->dev, "%s\n", __func__); 766 + 767 + hid_ishtp_cl_deinit(hid_ishtp_cl); 768 + 769 + hid_ishtp_cl = ishtp_cl_allocate(cl_device->ishtp_dev); 770 + if (!hid_ishtp_cl) 771 + return; 772 + 773 + cl_device->driver_data = hid_ishtp_cl; 774 + hid_ishtp_cl->client_data = client_data; 775 + client_data->hid_ishtp_cl = hid_ishtp_cl; 776 + 777 + client_data->num_hid_devices = 0; 778 + 779 + for (retry = 0; retry < 3; ++retry) { 780 + rv = hid_ishtp_cl_init(hid_ishtp_cl, 1); 781 + if (!rv) 782 + break; 783 + dev_err(&client_data->cl_device->dev, "Retry reset init\n"); 784 + } 785 + if (rv) { 786 + dev_err(&client_data->cl_device->dev, "Reset Failed\n"); 787 + hid_ishtp_trace(client_data, "%s Failed hid_ishtp_cl %p\n", 788 + __func__, hid_ishtp_cl); 789 + } 790 + } 791 + 792 + /** 793 + * hid_ishtp_cl_probe() - ISHTP client driver probe 794 + * @cl_device: ISHTP client device instance 795 + * 796 + * This function gets called on device create on ISHTP bus 797 + * 798 + * Return: 0 on success, non zero on error 799 + */ 800 + static int hid_ishtp_cl_probe(struct ishtp_cl_device *cl_device) 801 + { 802 + struct ishtp_cl *hid_ishtp_cl; 803 + struct ishtp_cl_data *client_data; 804 + int rv; 805 + 806 + if (!cl_device) 807 + return -ENODEV; 808 + 809 + if (uuid_le_cmp(hid_ishtp_guid, 810 + cl_device->fw_client->props.protocol_name) != 0) 811 + return -ENODEV; 812 + 813 + client_data = devm_kzalloc(&cl_device->dev, sizeof(*client_data), 814 + GFP_KERNEL); 815 + if (!client_data) 816 + return -ENOMEM; 817 + 818 + hid_ishtp_cl = ishtp_cl_allocate(cl_device->ishtp_dev); 819 + if (!hid_ishtp_cl) 820 + return -ENOMEM; 821 + 822 + cl_device->driver_data = hid_ishtp_cl; 823 + hid_ishtp_cl->client_data = client_data; 824 + client_data->hid_ishtp_cl = hid_ishtp_cl; 825 + client_data->cl_device = cl_device; 826 + 827 + init_waitqueue_head(&client_data->init_wait); 828 + init_waitqueue_head(&client_data->ishtp_resume_wait); 829 + 830 + INIT_WORK(&client_data->work, hid_ishtp_cl_reset_handler); 831 + 832 + rv = hid_ishtp_cl_init(hid_ishtp_cl, 0); 833 + if (rv) { 834 + ishtp_cl_free(hid_ishtp_cl); 835 + return rv; 836 + } 837 + ishtp_get_device(cl_device); 838 + 839 + return 0; 840 + } 841 + 842 + /** 843 + * hid_ishtp_cl_remove() - ISHTP client driver remove 844 + * @cl_device: ISHTP client device instance 845 + * 846 + * This function gets called on device remove on ISHTP bus 847 + * 848 + * Return: 0 849 + */ 850 + static int hid_ishtp_cl_remove(struct ishtp_cl_device *cl_device) 851 + { 852 + struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data; 853 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 854 + 855 + hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__, 856 + hid_ishtp_cl); 857 + 858 + dev_dbg(&cl_device->dev, "%s\n", __func__); 859 + hid_ishtp_cl->state = ISHTP_CL_DISCONNECTING; 860 + ishtp_cl_disconnect(hid_ishtp_cl); 861 + ishtp_put_device(cl_device); 862 + ishtp_hid_remove(client_data); 863 + hid_ishtp_cl_deinit(hid_ishtp_cl); 864 + 865 + hid_ishtp_cl = NULL; 866 + 867 + client_data->num_hid_devices = 0; 868 + 869 + return 0; 870 + } 871 + 872 + /** 873 + * hid_ishtp_cl_reset() - ISHTP client driver reset 874 + * @cl_device: ISHTP client device instance 875 + * 876 + * This function gets called on device reset on ISHTP bus 877 + * 878 + * Return: 0 879 + */ 880 + static int hid_ishtp_cl_reset(struct ishtp_cl_device *cl_device) 881 + { 882 + struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data; 883 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 884 + 885 + hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__, 886 + hid_ishtp_cl); 887 + 888 + schedule_work(&client_data->work); 889 + 890 + return 0; 891 + } 892 + 893 + #define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev) 894 + 895 + /** 896 + * hid_ishtp_cl_suspend() - ISHTP client driver suspend 897 + * @device: device instance 898 + * 899 + * This function gets called on system suspend 900 + * 901 + * Return: 0 902 + */ 903 + static int hid_ishtp_cl_suspend(struct device *device) 904 + { 905 + struct ishtp_cl_device *cl_device = to_ishtp_cl_device(device); 906 + struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data; 907 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 908 + 909 + hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__, 910 + hid_ishtp_cl); 911 + client_data->suspended = true; 912 + 913 + return 0; 914 + } 915 + 916 + /** 917 + * hid_ishtp_cl_resume() - ISHTP client driver resume 918 + * @device: device instance 919 + * 920 + * This function gets called on system resume 921 + * 922 + * Return: 0 923 + */ 924 + static int hid_ishtp_cl_resume(struct device *device) 925 + { 926 + struct ishtp_cl_device *cl_device = to_ishtp_cl_device(device); 927 + struct ishtp_cl *hid_ishtp_cl = cl_device->driver_data; 928 + struct ishtp_cl_data *client_data = hid_ishtp_cl->client_data; 929 + 930 + hid_ishtp_trace(client_data, "%s hid_ishtp_cl %p\n", __func__, 931 + hid_ishtp_cl); 932 + client_data->suspended = false; 933 + return 0; 934 + } 935 + 936 + static const struct dev_pm_ops hid_ishtp_pm_ops = { 937 + .suspend = hid_ishtp_cl_suspend, 938 + .resume = hid_ishtp_cl_resume, 939 + }; 940 + 941 + static struct ishtp_cl_driver hid_ishtp_cl_driver = { 942 + .name = "ish-hid", 943 + .probe = hid_ishtp_cl_probe, 944 + .remove = hid_ishtp_cl_remove, 945 + .reset = hid_ishtp_cl_reset, 946 + .driver.pm = &hid_ishtp_pm_ops, 947 + }; 948 + 949 + static int __init ish_hid_init(void) 950 + { 951 + int rv; 952 + 953 + /* Register ISHTP client device driver with ISHTP Bus */ 954 + rv = ishtp_cl_driver_register(&hid_ishtp_cl_driver); 955 + 956 + return rv; 957 + 958 + } 959 + 960 + static void __exit ish_hid_exit(void) 961 + { 962 + ishtp_cl_driver_unregister(&hid_ishtp_cl_driver); 963 + } 964 + 965 + late_initcall(ish_hid_init); 966 + module_exit(ish_hid_exit); 967 + 968 + MODULE_DESCRIPTION("ISH ISHTP HID client driver"); 969 + /* Primary author */ 970 + MODULE_AUTHOR("Daniel Drubin <daniel.drubin@intel.com>"); 971 + /* 972 + * Several modification for multi instance support 973 + * suspend/resume and clean up 974 + */ 975 + MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>"); 976 + 977 + MODULE_LICENSE("GPL"); 978 + MODULE_ALIAS("ishtp:*");
+246
drivers/hid/intel-ish-hid/ishtp-hid.c
··· 1 + /* 2 + * ISHTP-HID glue driver. 3 + * 4 + * Copyright (c) 2012-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include <linux/hid.h> 17 + #include <uapi/linux/input.h> 18 + #include "ishtp/client.h" 19 + #include "ishtp-hid.h" 20 + 21 + /** 22 + * ishtp_hid_parse() - hid-core .parse() callback 23 + * @hid: hid device instance 24 + * 25 + * This function gets called during call to hid_add_device 26 + * 27 + * Return: 0 on success and non zero on error 28 + */ 29 + static int ishtp_hid_parse(struct hid_device *hid) 30 + { 31 + struct ishtp_hid_data *hid_data = hid->driver_data; 32 + struct ishtp_cl_data *client_data = hid_data->client_data; 33 + int rv; 34 + 35 + rv = hid_parse_report(hid, client_data->report_descr[hid_data->index], 36 + client_data->report_descr_size[hid_data->index]); 37 + if (rv) 38 + return rv; 39 + 40 + return 0; 41 + } 42 + 43 + /* Empty callbacks with success return code */ 44 + static int ishtp_hid_start(struct hid_device *hid) 45 + { 46 + return 0; 47 + } 48 + 49 + static void ishtp_hid_stop(struct hid_device *hid) 50 + { 51 + } 52 + 53 + static int ishtp_hid_open(struct hid_device *hid) 54 + { 55 + return 0; 56 + } 57 + 58 + static void ishtp_hid_close(struct hid_device *hid) 59 + { 60 + } 61 + 62 + static int ishtp_raw_request(struct hid_device *hdev, unsigned char reportnum, 63 + __u8 *buf, size_t len, unsigned char rtype, int reqtype) 64 + { 65 + return 0; 66 + } 67 + 68 + /** 69 + * ishtp_hid_request() - hid-core .request() callback 70 + * @hid: hid device instance 71 + * @rep: pointer to hid_report 72 + * @reqtype: type of req. [GET|SET]_REPORT 73 + * 74 + * This function is used to set/get feaure/input report. 75 + */ 76 + static void ishtp_hid_request(struct hid_device *hid, struct hid_report *rep, 77 + int reqtype) 78 + { 79 + struct ishtp_hid_data *hid_data = hid->driver_data; 80 + /* the specific report length, just HID part of it */ 81 + unsigned int len = ((rep->size - 1) >> 3) + 1 + (rep->id > 0); 82 + char *buf; 83 + unsigned int header_size = sizeof(struct hostif_msg); 84 + 85 + len += header_size; 86 + 87 + hid_data->request_done = false; 88 + switch (reqtype) { 89 + case HID_REQ_GET_REPORT: 90 + hid_ishtp_get_report(hid, rep->id, rep->type); 91 + break; 92 + case HID_REQ_SET_REPORT: 93 + /* 94 + * Spare 7 bytes for 64b accesses through 95 + * get/put_unaligned_le64() 96 + */ 97 + buf = kzalloc(len + 7, GFP_KERNEL); 98 + if (!buf) 99 + return; 100 + 101 + hid_output_report(rep, buf + header_size); 102 + hid_ishtp_set_feature(hid, buf, len, rep->id); 103 + kfree(buf); 104 + break; 105 + } 106 + } 107 + 108 + /** 109 + * ishtp_wait_for_response() - hid-core .wait() callback 110 + * @hid: hid device instance 111 + * 112 + * This function is used to wait after get feaure/input report. 113 + * 114 + * Return: 0 on success and non zero on error 115 + */ 116 + static int ishtp_wait_for_response(struct hid_device *hid) 117 + { 118 + struct ishtp_hid_data *hid_data = hid->driver_data; 119 + struct ishtp_cl_data *client_data = hid_data->client_data; 120 + int rv; 121 + 122 + hid_ishtp_trace(client_data, "%s hid %p\n", __func__, hid); 123 + 124 + rv = ishtp_hid_link_ready_wait(hid_data->client_data); 125 + if (rv) 126 + return rv; 127 + 128 + if (!hid_data->request_done) 129 + wait_event_interruptible_timeout(hid_data->hid_wait, 130 + hid_data->request_done, 3 * HZ); 131 + 132 + if (!hid_data->request_done) { 133 + hid_err(hid, 134 + "timeout waiting for response from ISHTP device\n"); 135 + return -ETIMEDOUT; 136 + } 137 + hid_ishtp_trace(client_data, "%s hid %p done\n", __func__, hid); 138 + 139 + hid_data->request_done = false; 140 + 141 + return 0; 142 + } 143 + 144 + /** 145 + * ishtp_hid_wakeup() - Wakeup caller 146 + * @hid: hid device instance 147 + * 148 + * This function will wakeup caller waiting for Get/Set feature report 149 + */ 150 + void ishtp_hid_wakeup(struct hid_device *hid) 151 + { 152 + struct ishtp_hid_data *hid_data = hid->driver_data; 153 + 154 + hid_data->request_done = true; 155 + wake_up_interruptible(&hid_data->hid_wait); 156 + } 157 + 158 + static struct hid_ll_driver ishtp_hid_ll_driver = { 159 + .parse = ishtp_hid_parse, 160 + .start = ishtp_hid_start, 161 + .stop = ishtp_hid_stop, 162 + .open = ishtp_hid_open, 163 + .close = ishtp_hid_close, 164 + .request = ishtp_hid_request, 165 + .wait = ishtp_wait_for_response, 166 + .raw_request = ishtp_raw_request 167 + }; 168 + 169 + /** 170 + * ishtp_hid_probe() - hid register ll driver 171 + * @cur_hid_dev: Index of hid device calling to register 172 + * @client_data: Client data pointer 173 + * 174 + * This function is used to allocate and add HID device. 175 + * 176 + * Return: 0 on success, non zero on error 177 + */ 178 + int ishtp_hid_probe(unsigned int cur_hid_dev, 179 + struct ishtp_cl_data *client_data) 180 + { 181 + int rv; 182 + struct hid_device *hid; 183 + struct ishtp_hid_data *hid_data; 184 + 185 + hid = hid_allocate_device(); 186 + if (IS_ERR(hid)) { 187 + rv = PTR_ERR(hid); 188 + return -ENOMEM; 189 + } 190 + 191 + hid_data = kzalloc(sizeof(*hid_data), GFP_KERNEL); 192 + if (!hid_data) { 193 + rv = -ENOMEM; 194 + goto err_hid_data; 195 + } 196 + 197 + hid_data->index = cur_hid_dev; 198 + hid_data->client_data = client_data; 199 + init_waitqueue_head(&hid_data->hid_wait); 200 + 201 + hid->driver_data = hid_data; 202 + 203 + client_data->hid_sensor_hubs[cur_hid_dev] = hid; 204 + 205 + hid->ll_driver = &ishtp_hid_ll_driver; 206 + hid->bus = BUS_INTEL_ISHTP; 207 + hid->dev.parent = &client_data->cl_device->dev; 208 + hid->version = le16_to_cpu(ISH_HID_VERSION); 209 + hid->vendor = le16_to_cpu(ISH_HID_VENDOR); 210 + hid->product = le16_to_cpu(ISH_HID_PRODUCT); 211 + snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", "hid-ishtp", 212 + hid->vendor, hid->product); 213 + 214 + rv = hid_add_device(hid); 215 + if (rv) 216 + goto err_hid_device; 217 + 218 + hid_ishtp_trace(client_data, "%s allocated hid %p\n", __func__, hid); 219 + 220 + return 0; 221 + 222 + err_hid_device: 223 + kfree(hid_data); 224 + err_hid_data: 225 + kfree(hid); 226 + return rv; 227 + } 228 + 229 + /** 230 + * ishtp_hid_probe() - Remove registered hid device 231 + * @client_data: client data pointer 232 + * 233 + * This function is used to destroy allocatd HID device. 234 + */ 235 + void ishtp_hid_remove(struct ishtp_cl_data *client_data) 236 + { 237 + int i; 238 + 239 + for (i = 0; i < client_data->num_hid_devices; ++i) { 240 + if (client_data->hid_sensor_hubs[i]) { 241 + kfree(client_data->hid_sensor_hubs[i]->driver_data); 242 + hid_destroy_device(client_data->hid_sensor_hubs[i]); 243 + client_data->hid_sensor_hubs[i] = NULL; 244 + } 245 + } 246 + }
+182
drivers/hid/intel-ish-hid/ishtp-hid.h
··· 1 + /* 2 + * ISHTP-HID glue driver's definitions. 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + #ifndef ISHTP_HID__H 16 + #define ISHTP_HID__H 17 + 18 + /* The fixed ISH product and vendor id */ 19 + #define ISH_HID_VENDOR 0x8086 20 + #define ISH_HID_PRODUCT 0x22D8 21 + #define ISH_HID_VERSION 0x0200 22 + 23 + #define CMD_MASK 0x7F 24 + #define IS_RESPONSE 0x80 25 + 26 + /* Used to dump to Linux trace buffer, if enabled */ 27 + #define hid_ishtp_trace(client, ...) \ 28 + client->cl_device->ishtp_dev->print_log(\ 29 + client->cl_device->ishtp_dev, __VA_ARGS__) 30 + 31 + /* ISH Transport protocol (ISHTP in short) GUID */ 32 + static const uuid_le hid_ishtp_guid = UUID_LE(0x33AECD58, 0xB679, 0x4E54, 33 + 0x9B, 0xD9, 0xA0, 0x4D, 0x34, 34 + 0xF0, 0xC2, 0x26); 35 + 36 + /* ISH HID message structure */ 37 + struct hostif_msg_hdr { 38 + uint8_t command; /* Bit 7: is_response */ 39 + uint8_t device_id; 40 + uint8_t status; 41 + uint8_t flags; 42 + uint16_t size; 43 + } __packed; 44 + 45 + struct hostif_msg { 46 + struct hostif_msg_hdr hdr; 47 + } __packed; 48 + 49 + struct hostif_msg_to_sensor { 50 + struct hostif_msg_hdr hdr; 51 + uint8_t report_id; 52 + } __packed; 53 + 54 + struct device_info { 55 + uint32_t dev_id; 56 + uint8_t dev_class; 57 + uint16_t pid; 58 + uint16_t vid; 59 + } __packed; 60 + 61 + struct ishtp_version { 62 + uint8_t major; 63 + uint8_t minor; 64 + uint8_t hotfix; 65 + uint16_t build; 66 + } __packed; 67 + 68 + /* struct for ISHTP aggregated input data */ 69 + struct report_list { 70 + uint16_t total_size; 71 + uint8_t num_of_reports; 72 + uint8_t flags; 73 + struct { 74 + uint16_t size_of_report; 75 + uint8_t report[1]; 76 + } __packed reports[1]; 77 + } __packed; 78 + 79 + /* HOSTIF commands */ 80 + #define HOSTIF_HID_COMMAND_BASE 0 81 + #define HOSTIF_GET_HID_DESCRIPTOR 0 82 + #define HOSTIF_GET_REPORT_DESCRIPTOR 1 83 + #define HOSTIF_GET_FEATURE_REPORT 2 84 + #define HOSTIF_SET_FEATURE_REPORT 3 85 + #define HOSTIF_GET_INPUT_REPORT 4 86 + #define HOSTIF_PUBLISH_INPUT_REPORT 5 87 + #define HOSTIF_PUBLISH_INPUT_REPORT_LIST 6 88 + #define HOSTIF_DM_COMMAND_BASE 32 89 + #define HOSTIF_DM_ENUM_DEVICES 33 90 + #define HOSTIF_DM_ADD_DEVICE 34 91 + 92 + #define MAX_HID_DEVICES 32 93 + 94 + /** 95 + * struct ishtp_cl_data - Encapsulate per ISH TP HID Client 96 + * @enum_device_done: Enum devices response complete flag 97 + * @hid_descr_done: HID descriptor complete flag 98 + * @report_descr_done: Get report descriptor complete flag 99 + * @init_done: Init process completed successfully 100 + * @suspended: System is under suspend state or in progress 101 + * @num_hid_devices: Number of HID devices enumerated in this client 102 + * @cur_hid_dev: This keeps track of the device index for which 103 + * initialization and registration with HID core 104 + * in progress. 105 + * @hid_devices: Store vid/pid/devid for each enumerated HID device 106 + * @report_descr: Stores the raw report descriptors for each HID device 107 + * @report_descr_size: Report description of size of above repo_descr[] 108 + * @hid_sensor_hubs: Pointer to hid_device for all HID device, so that 109 + * when clients are removed, they can be freed 110 + * @hid_descr: Pointer to hid descriptor for each enumerated hid 111 + * device 112 + * @hid_descr_size: Size of each above report descriptor 113 + * @init_wait: Wait queue to wait during initialization, where the 114 + * client send message to ISH FW and wait for response 115 + * @ishtp_hid_wait: The wait for get report during wait callback from hid 116 + * core 117 + * @bad_recv_cnt: Running count of packets received with error 118 + * @multi_packet_cnt: Count of fragmented packet count 119 + * 120 + * This structure is used to store completion flags and per client data like 121 + * like report description, number of HID devices etc. 122 + */ 123 + struct ishtp_cl_data { 124 + /* completion flags */ 125 + bool enum_devices_done; 126 + bool hid_descr_done; 127 + bool report_descr_done; 128 + bool init_done; 129 + bool suspended; 130 + 131 + unsigned int num_hid_devices; 132 + unsigned int cur_hid_dev; 133 + unsigned int hid_dev_count; 134 + 135 + struct device_info *hid_devices; 136 + unsigned char *report_descr[MAX_HID_DEVICES]; 137 + int report_descr_size[MAX_HID_DEVICES]; 138 + struct hid_device *hid_sensor_hubs[MAX_HID_DEVICES]; 139 + unsigned char *hid_descr[MAX_HID_DEVICES]; 140 + int hid_descr_size[MAX_HID_DEVICES]; 141 + 142 + wait_queue_head_t init_wait; 143 + wait_queue_head_t ishtp_resume_wait; 144 + struct ishtp_cl *hid_ishtp_cl; 145 + 146 + /* Statistics */ 147 + unsigned int bad_recv_cnt; 148 + int multi_packet_cnt; 149 + 150 + struct work_struct work; 151 + struct ishtp_cl_device *cl_device; 152 + }; 153 + 154 + /** 155 + * struct ishtp_hid_data - Per instance HID data 156 + * @index: Device index in the order of enumeration 157 + * @request_done: Get Feature/Input report complete flag 158 + * used during get/set request from hid core 159 + * @client_data: Link to the client instance 160 + * @hid_wait: Completion waitq 161 + * 162 + * Used to tie hid hid->driver data to driver client instance 163 + */ 164 + struct ishtp_hid_data { 165 + int index; 166 + bool request_done; 167 + struct ishtp_cl_data *client_data; 168 + wait_queue_head_t hid_wait; 169 + }; 170 + 171 + /* Interface functions between HID LL driver and ISH TP client */ 172 + void hid_ishtp_set_feature(struct hid_device *hid, char *buf, unsigned int len, 173 + int report_id); 174 + void hid_ishtp_get_report(struct hid_device *hid, int report_id, 175 + int report_type); 176 + int ishtp_hid_probe(unsigned int cur_hid_dev, 177 + struct ishtp_cl_data *client_data); 178 + void ishtp_hid_remove(struct ishtp_cl_data *client_data); 179 + int ishtp_hid_link_ready_wait(struct ishtp_cl_data *client_data); 180 + void ishtp_hid_wakeup(struct hid_device *hid); 181 + 182 + #endif /* ISHTP_HID__H */
+788
drivers/hid/intel-ish-hid/ishtp/bus.c
··· 1 + /* 2 + * ISHTP bus driver 3 + * 4 + * Copyright (c) 2012-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include <linux/module.h> 17 + #include <linux/init.h> 18 + #include <linux/kernel.h> 19 + #include <linux/device.h> 20 + #include <linux/sched.h> 21 + #include <linux/slab.h> 22 + #include "bus.h" 23 + #include "ishtp-dev.h" 24 + #include "client.h" 25 + #include "hbm.h" 26 + 27 + static int ishtp_use_dma; 28 + module_param_named(ishtp_use_dma, ishtp_use_dma, int, 0600); 29 + MODULE_PARM_DESC(ishtp_use_dma, "Use DMA to send messages"); 30 + 31 + #define to_ishtp_cl_driver(d) container_of(d, struct ishtp_cl_driver, driver) 32 + #define to_ishtp_cl_device(d) container_of(d, struct ishtp_cl_device, dev) 33 + static bool ishtp_device_ready; 34 + 35 + /** 36 + * ishtp_recv() - process ishtp message 37 + * @dev: ishtp device 38 + * 39 + * If a message with valid header and size is received, then 40 + * this function calls appropriate handler. The host or firmware 41 + * address is zero, then they are host bus management message, 42 + * otherwise they are message fo clients. 43 + */ 44 + void ishtp_recv(struct ishtp_device *dev) 45 + { 46 + uint32_t msg_hdr; 47 + struct ishtp_msg_hdr *ishtp_hdr; 48 + 49 + /* Read ISHTP header dword */ 50 + msg_hdr = dev->ops->ishtp_read_hdr(dev); 51 + if (!msg_hdr) 52 + return; 53 + 54 + dev->ops->sync_fw_clock(dev); 55 + 56 + ishtp_hdr = (struct ishtp_msg_hdr *)&msg_hdr; 57 + dev->ishtp_msg_hdr = msg_hdr; 58 + 59 + /* Sanity check: ISHTP frag. length in header */ 60 + if (ishtp_hdr->length > dev->mtu) { 61 + dev_err(dev->devc, 62 + "ISHTP hdr - bad length: %u; dropped [%08X]\n", 63 + (unsigned int)ishtp_hdr->length, msg_hdr); 64 + return; 65 + } 66 + 67 + /* ISHTP bus message */ 68 + if (!ishtp_hdr->host_addr && !ishtp_hdr->fw_addr) 69 + recv_hbm(dev, ishtp_hdr); 70 + /* ISHTP fixed-client message */ 71 + else if (!ishtp_hdr->host_addr) 72 + recv_fixed_cl_msg(dev, ishtp_hdr); 73 + else 74 + /* ISHTP client message */ 75 + recv_ishtp_cl_msg(dev, ishtp_hdr); 76 + } 77 + EXPORT_SYMBOL(ishtp_recv); 78 + 79 + /** 80 + * ishtp_send_msg() - Send ishtp message 81 + * @dev: ishtp device 82 + * @hdr: Message header 83 + * @msg: Message contents 84 + * @ipc_send_compl: completion callback 85 + * @ipc_send_compl_prm: completion callback parameter 86 + * 87 + * Send a multi fragment message via IPC. After sending the first fragment 88 + * the completion callback is called to schedule transmit of next fragment. 89 + * 90 + * Return: This returns IPC send message status. 91 + */ 92 + int ishtp_send_msg(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr, 93 + void *msg, void(*ipc_send_compl)(void *), 94 + void *ipc_send_compl_prm) 95 + { 96 + unsigned char ipc_msg[IPC_FULL_MSG_SIZE]; 97 + uint32_t drbl_val; 98 + 99 + drbl_val = dev->ops->ipc_get_header(dev, hdr->length + 100 + sizeof(struct ishtp_msg_hdr), 101 + 1); 102 + 103 + memcpy(ipc_msg, &drbl_val, sizeof(uint32_t)); 104 + memcpy(ipc_msg + sizeof(uint32_t), hdr, sizeof(uint32_t)); 105 + memcpy(ipc_msg + 2 * sizeof(uint32_t), msg, hdr->length); 106 + return dev->ops->write(dev, ipc_send_compl, ipc_send_compl_prm, 107 + ipc_msg, 2 * sizeof(uint32_t) + hdr->length); 108 + } 109 + 110 + /** 111 + * ishtp_write_message() - Send ishtp single fragment message 112 + * @dev: ishtp device 113 + * @hdr: Message header 114 + * @buf: message data 115 + * 116 + * Send a single fragment message via IPC. This returns IPC send message 117 + * status. 118 + * 119 + * Return: This returns IPC send message status. 120 + */ 121 + int ishtp_write_message(struct ishtp_device *dev, struct ishtp_msg_hdr *hdr, 122 + unsigned char *buf) 123 + { 124 + return ishtp_send_msg(dev, hdr, buf, NULL, NULL); 125 + } 126 + 127 + /** 128 + * ishtp_fw_cl_by_uuid() - locate index of fw client 129 + * @dev: ishtp device 130 + * @uuid: uuid of the client to search 131 + * 132 + * Search firmware client using UUID. 133 + * 134 + * Return: fw client index or -ENOENT if not found 135 + */ 136 + int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const uuid_le *uuid) 137 + { 138 + int i, res = -ENOENT; 139 + 140 + for (i = 0; i < dev->fw_clients_num; ++i) { 141 + if (uuid_le_cmp(*uuid, dev->fw_clients[i].props.protocol_name) 142 + == 0) { 143 + res = i; 144 + break; 145 + } 146 + } 147 + return res; 148 + } 149 + EXPORT_SYMBOL(ishtp_fw_cl_by_uuid); 150 + 151 + /** 152 + * ishtp_fw_cl_by_id() - return index to fw_clients for client_id 153 + * @dev: the ishtp device structure 154 + * @client_id: fw client id to search 155 + * 156 + * Search firmware client using client id. 157 + * 158 + * Return: index on success, -ENOENT on failure. 159 + */ 160 + int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id) 161 + { 162 + int i, res = -ENOENT; 163 + unsigned long flags; 164 + 165 + spin_lock_irqsave(&dev->fw_clients_lock, flags); 166 + for (i = 0; i < dev->fw_clients_num; i++) { 167 + if (dev->fw_clients[i].client_id == client_id) { 168 + res = i; 169 + break; 170 + } 171 + } 172 + spin_unlock_irqrestore(&dev->fw_clients_lock, flags); 173 + 174 + return res; 175 + } 176 + 177 + /** 178 + * ishtp_cl_device_probe() - Bus probe() callback 179 + * @dev: the device structure 180 + * 181 + * This is a bus probe callback and calls the drive probe function. 182 + * 183 + * Return: Return value from driver probe() call. 184 + */ 185 + static int ishtp_cl_device_probe(struct device *dev) 186 + { 187 + struct ishtp_cl_device *device = to_ishtp_cl_device(dev); 188 + struct ishtp_cl_driver *driver; 189 + 190 + if (!device) 191 + return 0; 192 + 193 + driver = to_ishtp_cl_driver(dev->driver); 194 + if (!driver || !driver->probe) 195 + return -ENODEV; 196 + 197 + return driver->probe(device); 198 + } 199 + 200 + /** 201 + * ishtp_cl_device_remove() - Bus remove() callback 202 + * @dev: the device structure 203 + * 204 + * This is a bus remove callback and calls the drive remove function. 205 + * Since the ISH driver model supports only built in, this is 206 + * primarily can be called during pci driver init failure. 207 + * 208 + * Return: Return value from driver remove() call. 209 + */ 210 + static int ishtp_cl_device_remove(struct device *dev) 211 + { 212 + struct ishtp_cl_device *device = to_ishtp_cl_device(dev); 213 + struct ishtp_cl_driver *driver; 214 + 215 + if (!device || !dev->driver) 216 + return 0; 217 + 218 + if (device->event_cb) { 219 + device->event_cb = NULL; 220 + cancel_work_sync(&device->event_work); 221 + } 222 + 223 + driver = to_ishtp_cl_driver(dev->driver); 224 + if (!driver->remove) { 225 + dev->driver = NULL; 226 + 227 + return 0; 228 + } 229 + 230 + return driver->remove(device); 231 + } 232 + 233 + /** 234 + * ishtp_cl_device_suspend() - Bus suspend callback 235 + * @dev: device 236 + * 237 + * Called during device suspend process. 238 + * 239 + * Return: Return value from driver suspend() call. 240 + */ 241 + static int ishtp_cl_device_suspend(struct device *dev) 242 + { 243 + struct ishtp_cl_device *device = to_ishtp_cl_device(dev); 244 + struct ishtp_cl_driver *driver; 245 + int ret = 0; 246 + 247 + if (!device) 248 + return 0; 249 + 250 + driver = to_ishtp_cl_driver(dev->driver); 251 + if (driver && driver->driver.pm) { 252 + if (driver->driver.pm->suspend) 253 + ret = driver->driver.pm->suspend(dev); 254 + } 255 + 256 + return ret; 257 + } 258 + 259 + /** 260 + * ishtp_cl_device_resume() - Bus resume callback 261 + * @dev: device 262 + * 263 + * Called during device resume process. 264 + * 265 + * Return: Return value from driver resume() call. 266 + */ 267 + static int ishtp_cl_device_resume(struct device *dev) 268 + { 269 + struct ishtp_cl_device *device = to_ishtp_cl_device(dev); 270 + struct ishtp_cl_driver *driver; 271 + int ret = 0; 272 + 273 + if (!device) 274 + return 0; 275 + 276 + /* 277 + * When ISH needs hard reset, it is done asynchrnously, hence bus 278 + * resume will be called before full ISH resume 279 + */ 280 + if (device->ishtp_dev->resume_flag) 281 + return 0; 282 + 283 + driver = to_ishtp_cl_driver(dev->driver); 284 + if (driver && driver->driver.pm) { 285 + if (driver->driver.pm->resume) 286 + ret = driver->driver.pm->resume(dev); 287 + } 288 + 289 + return ret; 290 + } 291 + 292 + /** 293 + * ishtp_cl_device_reset() - Reset callback 294 + * @device: ishtp client device instance 295 + * 296 + * This is a callback when HW reset is done and the device need 297 + * reinit. 298 + * 299 + * Return: Return value from driver reset() call. 300 + */ 301 + static int ishtp_cl_device_reset(struct ishtp_cl_device *device) 302 + { 303 + struct ishtp_cl_driver *driver; 304 + int ret = 0; 305 + 306 + device->event_cb = NULL; 307 + cancel_work_sync(&device->event_work); 308 + 309 + driver = to_ishtp_cl_driver(device->dev.driver); 310 + if (driver && driver->reset) 311 + ret = driver->reset(device); 312 + 313 + return ret; 314 + } 315 + 316 + static ssize_t modalias_show(struct device *dev, struct device_attribute *a, 317 + char *buf) 318 + { 319 + int len; 320 + 321 + len = snprintf(buf, PAGE_SIZE, "ishtp:%s\n", dev_name(dev)); 322 + return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len; 323 + } 324 + 325 + static struct device_attribute ishtp_cl_dev_attrs[] = { 326 + __ATTR_RO(modalias), 327 + __ATTR_NULL, 328 + }; 329 + 330 + static int ishtp_cl_uevent(struct device *dev, struct kobj_uevent_env *env) 331 + { 332 + if (add_uevent_var(env, "MODALIAS=ishtp:%s", dev_name(dev))) 333 + return -ENOMEM; 334 + return 0; 335 + } 336 + 337 + static const struct dev_pm_ops ishtp_cl_bus_dev_pm_ops = { 338 + /* Suspend callbacks */ 339 + .suspend = ishtp_cl_device_suspend, 340 + .resume = ishtp_cl_device_resume, 341 + /* Hibernate callbacks */ 342 + .freeze = ishtp_cl_device_suspend, 343 + .thaw = ishtp_cl_device_resume, 344 + .restore = ishtp_cl_device_resume, 345 + }; 346 + 347 + static struct bus_type ishtp_cl_bus_type = { 348 + .name = "ishtp", 349 + .dev_attrs = ishtp_cl_dev_attrs, 350 + .probe = ishtp_cl_device_probe, 351 + .remove = ishtp_cl_device_remove, 352 + .pm = &ishtp_cl_bus_dev_pm_ops, 353 + .uevent = ishtp_cl_uevent, 354 + }; 355 + 356 + static void ishtp_cl_dev_release(struct device *dev) 357 + { 358 + kfree(to_ishtp_cl_device(dev)); 359 + } 360 + 361 + static struct device_type ishtp_cl_device_type = { 362 + .release = ishtp_cl_dev_release, 363 + }; 364 + 365 + /** 366 + * ishtp_bus_add_device() - Function to create device on bus 367 + * @dev: ishtp device 368 + * @uuid: uuid of the client 369 + * @name: Name of the client 370 + * 371 + * Allocate ISHTP bus client device, attach it to uuid 372 + * and register with ISHTP bus. 373 + * 374 + * Return: ishtp_cl_device pointer or NULL on failure 375 + */ 376 + static struct ishtp_cl_device *ishtp_bus_add_device(struct ishtp_device *dev, 377 + uuid_le uuid, char *name) 378 + { 379 + struct ishtp_cl_device *device; 380 + int status; 381 + unsigned long flags; 382 + 383 + spin_lock_irqsave(&dev->device_list_lock, flags); 384 + list_for_each_entry(device, &dev->device_list, device_link) { 385 + if (!strcmp(name, dev_name(&device->dev))) { 386 + device->fw_client = &dev->fw_clients[ 387 + dev->fw_client_presentation_num - 1]; 388 + spin_unlock_irqrestore(&dev->device_list_lock, flags); 389 + ishtp_cl_device_reset(device); 390 + return device; 391 + } 392 + } 393 + spin_unlock_irqrestore(&dev->device_list_lock, flags); 394 + 395 + device = kzalloc(sizeof(struct ishtp_cl_device), GFP_KERNEL); 396 + if (!device) 397 + return NULL; 398 + 399 + device->dev.parent = dev->devc; 400 + device->dev.bus = &ishtp_cl_bus_type; 401 + device->dev.type = &ishtp_cl_device_type; 402 + device->ishtp_dev = dev; 403 + 404 + device->fw_client = 405 + &dev->fw_clients[dev->fw_client_presentation_num - 1]; 406 + 407 + dev_set_name(&device->dev, "%s", name); 408 + 409 + spin_lock_irqsave(&dev->device_list_lock, flags); 410 + list_add_tail(&device->device_link, &dev->device_list); 411 + spin_unlock_irqrestore(&dev->device_list_lock, flags); 412 + 413 + status = device_register(&device->dev); 414 + if (status) { 415 + spin_lock_irqsave(&dev->device_list_lock, flags); 416 + list_del(&device->device_link); 417 + spin_unlock_irqrestore(&dev->device_list_lock, flags); 418 + dev_err(dev->devc, "Failed to register ISHTP client device\n"); 419 + kfree(device); 420 + return NULL; 421 + } 422 + 423 + ishtp_device_ready = true; 424 + 425 + return device; 426 + } 427 + 428 + /** 429 + * ishtp_bus_remove_device() - Function to relase device on bus 430 + * @device: client device instance 431 + * 432 + * This is a counterpart of ishtp_bus_add_device. 433 + * Device is unregistered. 434 + * the device structure is freed in 'ishtp_cl_dev_release' function 435 + * Called only during error in pci driver init path. 436 + */ 437 + static void ishtp_bus_remove_device(struct ishtp_cl_device *device) 438 + { 439 + device_unregister(&device->dev); 440 + } 441 + 442 + /** 443 + * __ishtp_cl_driver_register() - Client driver register 444 + * @driver: the client driver instance 445 + * @owner: Owner of this driver module 446 + * 447 + * Once a client driver is probed, it created a client 448 + * instance and registers with the bus. 449 + * 450 + * Return: Return value of driver_register or -ENODEV if not ready 451 + */ 452 + int __ishtp_cl_driver_register(struct ishtp_cl_driver *driver, 453 + struct module *owner) 454 + { 455 + int err; 456 + 457 + if (!ishtp_device_ready) 458 + return -ENODEV; 459 + 460 + driver->driver.name = driver->name; 461 + driver->driver.owner = owner; 462 + driver->driver.bus = &ishtp_cl_bus_type; 463 + 464 + err = driver_register(&driver->driver); 465 + if (err) 466 + return err; 467 + 468 + return 0; 469 + } 470 + EXPORT_SYMBOL(__ishtp_cl_driver_register); 471 + 472 + /** 473 + * ishtp_cl_driver_unregister() - Client driver unregister 474 + * @driver: the client driver instance 475 + * 476 + * Unregister client during device removal process. 477 + */ 478 + void ishtp_cl_driver_unregister(struct ishtp_cl_driver *driver) 479 + { 480 + driver_unregister(&driver->driver); 481 + } 482 + EXPORT_SYMBOL(ishtp_cl_driver_unregister); 483 + 484 + /** 485 + * ishtp_bus_event_work() - event work function 486 + * @work: work struct pointer 487 + * 488 + * Once an event is received for a client this work 489 + * function is called. If the device has registered a 490 + * callback then the callback is called. 491 + */ 492 + static void ishtp_bus_event_work(struct work_struct *work) 493 + { 494 + struct ishtp_cl_device *device; 495 + 496 + device = container_of(work, struct ishtp_cl_device, event_work); 497 + 498 + if (device->event_cb) 499 + device->event_cb(device); 500 + } 501 + 502 + /** 503 + * ishtp_cl_bus_rx_event() - schedule event work 504 + * @device: client device instance 505 + * 506 + * Once an event is received for a client this schedules 507 + * a work function to process. 508 + */ 509 + void ishtp_cl_bus_rx_event(struct ishtp_cl_device *device) 510 + { 511 + if (!device || !device->event_cb) 512 + return; 513 + 514 + if (device->event_cb) 515 + schedule_work(&device->event_work); 516 + } 517 + 518 + /** 519 + * ishtp_register_event_cb() - Register callback 520 + * @device: client device instance 521 + * @event_cb: Event processor for an client 522 + * 523 + * Register a callback for events, called from client driver 524 + * 525 + * Return: Return 0 or -EALREADY if already registered 526 + */ 527 + int ishtp_register_event_cb(struct ishtp_cl_device *device, 528 + void (*event_cb)(struct ishtp_cl_device *)) 529 + { 530 + if (device->event_cb) 531 + return -EALREADY; 532 + 533 + device->event_cb = event_cb; 534 + INIT_WORK(&device->event_work, ishtp_bus_event_work); 535 + 536 + return 0; 537 + } 538 + EXPORT_SYMBOL(ishtp_register_event_cb); 539 + 540 + /** 541 + * ishtp_get_device() - update usage count for the device 542 + * @cl_device: client device instance 543 + * 544 + * Increment the usage count. The device can't be deleted 545 + */ 546 + void ishtp_get_device(struct ishtp_cl_device *cl_device) 547 + { 548 + cl_device->reference_count++; 549 + } 550 + EXPORT_SYMBOL(ishtp_get_device); 551 + 552 + /** 553 + * ishtp_put_device() - decrement usage count for the device 554 + * @cl_device: client device instance 555 + * 556 + * Decrement the usage count. The device can be deleted is count = 0 557 + */ 558 + void ishtp_put_device(struct ishtp_cl_device *cl_device) 559 + { 560 + cl_device->reference_count--; 561 + } 562 + EXPORT_SYMBOL(ishtp_put_device); 563 + 564 + /** 565 + * ishtp_bus_new_client() - Create a new client 566 + * @dev: ISHTP device instance 567 + * 568 + * Once bus protocol enumerates a client, this is called 569 + * to add a device for the client. 570 + * 571 + * Return: 0 on success or error code on failure 572 + */ 573 + int ishtp_bus_new_client(struct ishtp_device *dev) 574 + { 575 + int i; 576 + char *dev_name; 577 + struct ishtp_cl_device *cl_device; 578 + uuid_le device_uuid; 579 + 580 + /* 581 + * For all reported clients, create an unconnected client and add its 582 + * device to ISHTP bus. 583 + * If appropriate driver has loaded, this will trigger its probe(). 584 + * Otherwise, probe() will be called when driver is loaded 585 + */ 586 + i = dev->fw_client_presentation_num - 1; 587 + device_uuid = dev->fw_clients[i].props.protocol_name; 588 + dev_name = kasprintf(GFP_KERNEL, 589 + "{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 590 + device_uuid.b[3], device_uuid.b[2], device_uuid.b[1], 591 + device_uuid.b[0], device_uuid.b[5], device_uuid.b[4], 592 + device_uuid.b[7], device_uuid.b[6], device_uuid.b[8], 593 + device_uuid.b[9], device_uuid.b[10], device_uuid.b[11], 594 + device_uuid.b[12], device_uuid.b[13], device_uuid.b[14], 595 + device_uuid.b[15]); 596 + if (!dev_name) 597 + return -ENOMEM; 598 + 599 + cl_device = ishtp_bus_add_device(dev, device_uuid, dev_name); 600 + if (!cl_device) { 601 + kfree(dev_name); 602 + return -ENOENT; 603 + } 604 + 605 + kfree(dev_name); 606 + 607 + return 0; 608 + } 609 + 610 + /** 611 + * ishtp_cl_device_bind() - bind a device 612 + * @cl: ishtp client device 613 + * 614 + * Binds connected ishtp_cl to ISHTP bus device 615 + * 616 + * Return: 0 on success or fault code 617 + */ 618 + int ishtp_cl_device_bind(struct ishtp_cl *cl) 619 + { 620 + struct ishtp_cl_device *cl_device; 621 + unsigned long flags; 622 + int rv; 623 + 624 + if (!cl->fw_client_id || cl->state != ISHTP_CL_CONNECTED) 625 + return -EFAULT; 626 + 627 + rv = -ENOENT; 628 + spin_lock_irqsave(&cl->dev->device_list_lock, flags); 629 + list_for_each_entry(cl_device, &cl->dev->device_list, 630 + device_link) { 631 + if (cl_device->fw_client->client_id == cl->fw_client_id) { 632 + cl->device = cl_device; 633 + rv = 0; 634 + break; 635 + } 636 + } 637 + spin_unlock_irqrestore(&cl->dev->device_list_lock, flags); 638 + return rv; 639 + } 640 + 641 + /** 642 + * ishtp_bus_remove_all_clients() - Remove all clients 643 + * @ishtp_dev: ishtp device 644 + * @warm_reset: Reset due to FW reset dure to errors or S3 suspend 645 + * 646 + * This is part of reset/remove flow. This function the main processing 647 + * only targets error processing, if the FW has forced reset or 648 + * error to remove connected clients. When warm reset the client devices are 649 + * not removed. 650 + */ 651 + void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev, 652 + bool warm_reset) 653 + { 654 + struct ishtp_cl_device *cl_device, *n; 655 + struct ishtp_cl *cl; 656 + unsigned long flags; 657 + 658 + spin_lock_irqsave(&ishtp_dev->cl_list_lock, flags); 659 + list_for_each_entry(cl, &ishtp_dev->cl_list, link) { 660 + cl->state = ISHTP_CL_DISCONNECTED; 661 + 662 + /* 663 + * Wake any pending process. The waiter would check dev->state 664 + * and determine that it's not enabled already, 665 + * and will return error to its caller 666 + */ 667 + wake_up_interruptible(&cl->wait_ctrl_res); 668 + 669 + /* Disband any pending read/write requests and free rb */ 670 + ishtp_cl_flush_queues(cl); 671 + 672 + /* Remove all free and in_process rings, both Rx and Tx */ 673 + ishtp_cl_free_rx_ring(cl); 674 + ishtp_cl_free_tx_ring(cl); 675 + 676 + /* 677 + * Free client and ISHTP bus client device structures 678 + * don't free host client because it is part of the OS fd 679 + * structure 680 + */ 681 + } 682 + spin_unlock_irqrestore(&ishtp_dev->cl_list_lock, flags); 683 + 684 + /* Release DMA buffers for client messages */ 685 + ishtp_cl_free_dma_buf(ishtp_dev); 686 + 687 + /* remove bus clients */ 688 + spin_lock_irqsave(&ishtp_dev->device_list_lock, flags); 689 + list_for_each_entry_safe(cl_device, n, &ishtp_dev->device_list, 690 + device_link) { 691 + if (warm_reset && cl_device->reference_count) 692 + continue; 693 + 694 + list_del(&cl_device->device_link); 695 + spin_unlock_irqrestore(&ishtp_dev->device_list_lock, flags); 696 + ishtp_bus_remove_device(cl_device); 697 + spin_lock_irqsave(&ishtp_dev->device_list_lock, flags); 698 + } 699 + spin_unlock_irqrestore(&ishtp_dev->device_list_lock, flags); 700 + 701 + /* Free all client structures */ 702 + spin_lock_irqsave(&ishtp_dev->fw_clients_lock, flags); 703 + kfree(ishtp_dev->fw_clients); 704 + ishtp_dev->fw_clients = NULL; 705 + ishtp_dev->fw_clients_num = 0; 706 + ishtp_dev->fw_client_presentation_num = 0; 707 + ishtp_dev->fw_client_index = 0; 708 + bitmap_zero(ishtp_dev->fw_clients_map, ISHTP_CLIENTS_MAX); 709 + spin_unlock_irqrestore(&ishtp_dev->fw_clients_lock, flags); 710 + } 711 + EXPORT_SYMBOL(ishtp_bus_remove_all_clients); 712 + 713 + /** 714 + * ishtp_reset_handler() - IPC reset handler 715 + * @dev: ishtp device 716 + * 717 + * ISHTP Handler for IPC_RESET notification 718 + */ 719 + void ishtp_reset_handler(struct ishtp_device *dev) 720 + { 721 + unsigned long flags; 722 + 723 + /* Handle FW-initiated reset */ 724 + dev->dev_state = ISHTP_DEV_RESETTING; 725 + 726 + /* Clear BH processing queue - no further HBMs */ 727 + spin_lock_irqsave(&dev->rd_msg_spinlock, flags); 728 + dev->rd_msg_fifo_head = dev->rd_msg_fifo_tail = 0; 729 + spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags); 730 + 731 + /* Handle ISH FW reset against upper layers */ 732 + ishtp_bus_remove_all_clients(dev, true); 733 + } 734 + EXPORT_SYMBOL(ishtp_reset_handler); 735 + 736 + /** 737 + * ishtp_reset_compl_handler() - Reset completion handler 738 + * @dev: ishtp device 739 + * 740 + * ISHTP handler for IPC_RESET sequence completion to start 741 + * host message bus start protocol sequence. 742 + */ 743 + void ishtp_reset_compl_handler(struct ishtp_device *dev) 744 + { 745 + dev->dev_state = ISHTP_DEV_INIT_CLIENTS; 746 + dev->hbm_state = ISHTP_HBM_START; 747 + ishtp_hbm_start_req(dev); 748 + } 749 + EXPORT_SYMBOL(ishtp_reset_compl_handler); 750 + 751 + /** 752 + * ishtp_use_dma_transfer() - Function to use DMA 753 + * 754 + * This interface is used to enable usage of DMA 755 + * 756 + * Return non zero if DMA can be enabled 757 + */ 758 + int ishtp_use_dma_transfer(void) 759 + { 760 + return ishtp_use_dma; 761 + } 762 + 763 + /** 764 + * ishtp_bus_register() - Function to register bus 765 + * 766 + * This register ishtp bus 767 + * 768 + * Return: Return output of bus_register 769 + */ 770 + static int __init ishtp_bus_register(void) 771 + { 772 + return bus_register(&ishtp_cl_bus_type); 773 + } 774 + 775 + /** 776 + * ishtp_bus_unregister() - Function to unregister bus 777 + * 778 + * This unregister ishtp bus 779 + */ 780 + static void __exit ishtp_bus_unregister(void) 781 + { 782 + bus_unregister(&ishtp_cl_bus_type); 783 + } 784 + 785 + module_init(ishtp_bus_register); 786 + module_exit(ishtp_bus_unregister); 787 + 788 + MODULE_LICENSE("GPL");
+114
drivers/hid/intel-ish-hid/ishtp/bus.h
··· 1 + /* 2 + * ISHTP bus definitions 3 + * 4 + * Copyright (c) 2014-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + #ifndef _LINUX_ISHTP_CL_BUS_H 16 + #define _LINUX_ISHTP_CL_BUS_H 17 + 18 + #include <linux/device.h> 19 + #include <linux/mod_devicetable.h> 20 + 21 + struct ishtp_cl; 22 + struct ishtp_cl_device; 23 + struct ishtp_device; 24 + struct ishtp_msg_hdr; 25 + 26 + /** 27 + * struct ishtp_cl_device - ISHTP device handle 28 + * @dev: device pointer 29 + * @ishtp_dev: pointer to ishtp device structure to primarily to access 30 + * hw device operation callbacks and properties 31 + * @fw_client: fw_client pointer to get fw information like protocol name 32 + * max message length etc. 33 + * @device_link: Link to next client in the list on a bus 34 + * @event_work: Used to schedule rx event for client 35 + * @driver_data: Storage driver private data 36 + * @reference_count: Used for get/put device 37 + * @event_cb: Callback to driver to send events 38 + * 39 + * An ishtp_cl_device pointer is returned from ishtp_add_device() 40 + * and links ISHTP bus clients to their actual host client pointer. 41 + * Drivers for ISHTP devices will get an ishtp_cl_device pointer 42 + * when being probed and shall use it for doing bus I/O. 43 + */ 44 + struct ishtp_cl_device { 45 + struct device dev; 46 + struct ishtp_device *ishtp_dev; 47 + struct ishtp_fw_client *fw_client; 48 + struct list_head device_link; 49 + struct work_struct event_work; 50 + void *driver_data; 51 + int reference_count; 52 + void (*event_cb)(struct ishtp_cl_device *device); 53 + }; 54 + 55 + /** 56 + * struct ishtp_cl_device - ISHTP device handle 57 + * @driver: driver instance on a bus 58 + * @name: Name of the device for probe 59 + * @probe: driver callback for device probe 60 + * @remove: driver callback on device removal 61 + * 62 + * Client drivers defines to get probed/removed for ISHTP client device. 63 + */ 64 + struct ishtp_cl_driver { 65 + struct device_driver driver; 66 + const char *name; 67 + int (*probe)(struct ishtp_cl_device *dev); 68 + int (*remove)(struct ishtp_cl_device *dev); 69 + int (*reset)(struct ishtp_cl_device *dev); 70 + const struct dev_pm_ops *pm; 71 + }; 72 + 73 + 74 + int ishtp_bus_new_client(struct ishtp_device *dev); 75 + void ishtp_remove_all_clients(struct ishtp_device *dev); 76 + int ishtp_cl_device_bind(struct ishtp_cl *cl); 77 + void ishtp_cl_bus_rx_event(struct ishtp_cl_device *device); 78 + 79 + /* Write a multi-fragment message */ 80 + int ishtp_send_msg(struct ishtp_device *dev, 81 + struct ishtp_msg_hdr *hdr, void *msg, 82 + void (*ipc_send_compl)(void *), 83 + void *ipc_send_compl_prm); 84 + 85 + /* Write a single-fragment message */ 86 + int ishtp_write_message(struct ishtp_device *dev, 87 + struct ishtp_msg_hdr *hdr, 88 + unsigned char *buf); 89 + 90 + /* Use DMA to send/receive messages */ 91 + int ishtp_use_dma_transfer(void); 92 + 93 + /* Exported functions */ 94 + void ishtp_bus_remove_all_clients(struct ishtp_device *ishtp_dev, 95 + bool warm_reset); 96 + 97 + void ishtp_recv(struct ishtp_device *dev); 98 + void ishtp_reset_handler(struct ishtp_device *dev); 99 + void ishtp_reset_compl_handler(struct ishtp_device *dev); 100 + 101 + void ishtp_put_device(struct ishtp_cl_device *); 102 + void ishtp_get_device(struct ishtp_cl_device *); 103 + 104 + int __ishtp_cl_driver_register(struct ishtp_cl_driver *driver, 105 + struct module *owner); 106 + #define ishtp_cl_driver_register(driver) \ 107 + __ishtp_cl_driver_register(driver, THIS_MODULE) 108 + void ishtp_cl_driver_unregister(struct ishtp_cl_driver *driver); 109 + 110 + int ishtp_register_event_cb(struct ishtp_cl_device *device, 111 + void (*read_cb)(struct ishtp_cl_device *)); 112 + int ishtp_fw_cl_by_uuid(struct ishtp_device *dev, const uuid_le *cuuid); 113 + 114 + #endif /* _LINUX_ISHTP_CL_BUS_H */
+257
drivers/hid/intel-ish-hid/ishtp/client-buffers.c
··· 1 + /* 2 + * ISHTP Ring Buffers 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + * 15 + */ 16 + 17 + #include <linux/slab.h> 18 + #include "client.h" 19 + 20 + /** 21 + * ishtp_cl_alloc_rx_ring() - Allocate RX ring buffers 22 + * @cl: client device instance 23 + * 24 + * Allocate and initialize RX ring buffers 25 + * 26 + * Return: 0 on success else -ENOMEM 27 + */ 28 + int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl) 29 + { 30 + size_t len = cl->device->fw_client->props.max_msg_length; 31 + int j; 32 + struct ishtp_cl_rb *rb; 33 + int ret = 0; 34 + unsigned long flags; 35 + 36 + for (j = 0; j < cl->rx_ring_size; ++j) { 37 + rb = ishtp_io_rb_init(cl); 38 + if (!rb) { 39 + ret = -ENOMEM; 40 + goto out; 41 + } 42 + ret = ishtp_io_rb_alloc_buf(rb, len); 43 + if (ret) 44 + goto out; 45 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 46 + list_add_tail(&rb->list, &cl->free_rb_list.list); 47 + spin_unlock_irqrestore(&cl->free_list_spinlock, flags); 48 + } 49 + 50 + return 0; 51 + 52 + out: 53 + dev_err(&cl->device->dev, "error in allocating Rx buffers\n"); 54 + ishtp_cl_free_rx_ring(cl); 55 + return ret; 56 + } 57 + 58 + /** 59 + * ishtp_cl_alloc_tx_ring() - Allocate TX ring buffers 60 + * @cl: client device instance 61 + * 62 + * Allocate and initialize TX ring buffers 63 + * 64 + * Return: 0 on success else -ENOMEM 65 + */ 66 + int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl) 67 + { 68 + size_t len = cl->device->fw_client->props.max_msg_length; 69 + int j; 70 + unsigned long flags; 71 + 72 + /* Allocate pool to free Tx bufs */ 73 + for (j = 0; j < cl->tx_ring_size; ++j) { 74 + struct ishtp_cl_tx_ring *tx_buf; 75 + 76 + tx_buf = kzalloc(sizeof(struct ishtp_cl_tx_ring), GFP_KERNEL); 77 + if (!tx_buf) 78 + goto out; 79 + 80 + tx_buf->send_buf.data = kmalloc(len, GFP_KERNEL); 81 + if (!tx_buf->send_buf.data) { 82 + kfree(tx_buf); 83 + goto out; 84 + } 85 + 86 + spin_lock_irqsave(&cl->tx_free_list_spinlock, flags); 87 + list_add_tail(&tx_buf->list, &cl->tx_free_list.list); 88 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags); 89 + } 90 + return 0; 91 + out: 92 + dev_err(&cl->device->dev, "error in allocating Tx pool\n"); 93 + ishtp_cl_free_rx_ring(cl); 94 + return -ENOMEM; 95 + } 96 + 97 + /** 98 + * ishtp_cl_free_rx_ring() - Free RX ring buffers 99 + * @cl: client device instance 100 + * 101 + * Free RX ring buffers 102 + */ 103 + void ishtp_cl_free_rx_ring(struct ishtp_cl *cl) 104 + { 105 + struct ishtp_cl_rb *rb; 106 + unsigned long flags; 107 + 108 + /* release allocated memory - pass over free_rb_list */ 109 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 110 + while (!list_empty(&cl->free_rb_list.list)) { 111 + rb = list_entry(cl->free_rb_list.list.next, struct ishtp_cl_rb, 112 + list); 113 + list_del(&rb->list); 114 + kfree(rb->buffer.data); 115 + kfree(rb); 116 + } 117 + spin_unlock_irqrestore(&cl->free_list_spinlock, flags); 118 + /* release allocated memory - pass over in_process_list */ 119 + spin_lock_irqsave(&cl->in_process_spinlock, flags); 120 + while (!list_empty(&cl->in_process_list.list)) { 121 + rb = list_entry(cl->in_process_list.list.next, 122 + struct ishtp_cl_rb, list); 123 + list_del(&rb->list); 124 + kfree(rb->buffer.data); 125 + kfree(rb); 126 + } 127 + spin_unlock_irqrestore(&cl->in_process_spinlock, flags); 128 + } 129 + 130 + /** 131 + * ishtp_cl_free_tx_ring() - Free TX ring buffers 132 + * @cl: client device instance 133 + * 134 + * Free TX ring buffers 135 + */ 136 + void ishtp_cl_free_tx_ring(struct ishtp_cl *cl) 137 + { 138 + struct ishtp_cl_tx_ring *tx_buf; 139 + unsigned long flags; 140 + 141 + spin_lock_irqsave(&cl->tx_free_list_spinlock, flags); 142 + /* release allocated memory - pass over tx_free_list */ 143 + while (!list_empty(&cl->tx_free_list.list)) { 144 + tx_buf = list_entry(cl->tx_free_list.list.next, 145 + struct ishtp_cl_tx_ring, list); 146 + list_del(&tx_buf->list); 147 + kfree(tx_buf->send_buf.data); 148 + kfree(tx_buf); 149 + } 150 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, flags); 151 + 152 + spin_lock_irqsave(&cl->tx_list_spinlock, flags); 153 + /* release allocated memory - pass over tx_list */ 154 + while (!list_empty(&cl->tx_list.list)) { 155 + tx_buf = list_entry(cl->tx_list.list.next, 156 + struct ishtp_cl_tx_ring, list); 157 + list_del(&tx_buf->list); 158 + kfree(tx_buf->send_buf.data); 159 + kfree(tx_buf); 160 + } 161 + spin_unlock_irqrestore(&cl->tx_list_spinlock, flags); 162 + } 163 + 164 + /** 165 + * ishtp_io_rb_free() - Free IO request block 166 + * @rb: IO request block 167 + * 168 + * Free io request block memory 169 + */ 170 + void ishtp_io_rb_free(struct ishtp_cl_rb *rb) 171 + { 172 + if (rb == NULL) 173 + return; 174 + 175 + kfree(rb->buffer.data); 176 + kfree(rb); 177 + } 178 + 179 + /** 180 + * ishtp_io_rb_init() - Allocate and init IO request block 181 + * @cl: client device instance 182 + * 183 + * Allocate and initialize request block 184 + * 185 + * Return: Allocted IO request block pointer 186 + */ 187 + struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl) 188 + { 189 + struct ishtp_cl_rb *rb; 190 + 191 + rb = kzalloc(sizeof(struct ishtp_cl_rb), GFP_KERNEL); 192 + if (!rb) 193 + return NULL; 194 + 195 + INIT_LIST_HEAD(&rb->list); 196 + rb->cl = cl; 197 + rb->buf_idx = 0; 198 + return rb; 199 + } 200 + 201 + /** 202 + * ishtp_io_rb_alloc_buf() - Allocate and init response buffer 203 + * @rb: IO request block 204 + * @length: length of response buffer 205 + * 206 + * Allocate respose buffer 207 + * 208 + * Return: 0 on success else -ENOMEM 209 + */ 210 + int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length) 211 + { 212 + if (!rb) 213 + return -EINVAL; 214 + 215 + if (length == 0) 216 + return 0; 217 + 218 + rb->buffer.data = kmalloc(length, GFP_KERNEL); 219 + if (!rb->buffer.data) 220 + return -ENOMEM; 221 + 222 + rb->buffer.size = length; 223 + return 0; 224 + } 225 + 226 + /** 227 + * ishtp_cl_io_rb_recycle() - Recycle IO request blocks 228 + * @rb: IO request block 229 + * 230 + * Re-append rb to its client's free list and send flow control if needed 231 + * 232 + * Return: 0 on success else -EFAULT 233 + */ 234 + int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb) 235 + { 236 + struct ishtp_cl *cl; 237 + int rets = 0; 238 + unsigned long flags; 239 + 240 + if (!rb || !rb->cl) 241 + return -EFAULT; 242 + 243 + cl = rb->cl; 244 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 245 + list_add_tail(&rb->list, &cl->free_rb_list.list); 246 + spin_unlock_irqrestore(&cl->free_list_spinlock, flags); 247 + 248 + /* 249 + * If we returned the first buffer to empty 'free' list, 250 + * send flow control 251 + */ 252 + if (!cl->out_flow_ctrl_creds) 253 + rets = ishtp_cl_read_start(cl); 254 + 255 + return rets; 256 + } 257 + EXPORT_SYMBOL(ishtp_cl_io_rb_recycle);
+1054
drivers/hid/intel-ish-hid/ishtp/client.c
··· 1 + /* 2 + * ISHTP client logic 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + * 15 + */ 16 + 17 + #include <linux/slab.h> 18 + #include <linux/sched.h> 19 + #include <linux/wait.h> 20 + #include <linux/delay.h> 21 + #include <linux/dma-mapping.h> 22 + #include "hbm.h" 23 + #include "client.h" 24 + 25 + /** 26 + * ishtp_read_list_flush() - Flush read queue 27 + * @cl: ishtp client instance 28 + * 29 + * Used to remove all entries from read queue for a client 30 + */ 31 + static void ishtp_read_list_flush(struct ishtp_cl *cl) 32 + { 33 + struct ishtp_cl_rb *rb; 34 + struct ishtp_cl_rb *next; 35 + unsigned long flags; 36 + 37 + spin_lock_irqsave(&cl->dev->read_list_spinlock, flags); 38 + list_for_each_entry_safe(rb, next, &cl->dev->read_list.list, list) 39 + if (rb->cl && ishtp_cl_cmp_id(cl, rb->cl)) { 40 + list_del(&rb->list); 41 + ishtp_io_rb_free(rb); 42 + } 43 + spin_unlock_irqrestore(&cl->dev->read_list_spinlock, flags); 44 + } 45 + 46 + /** 47 + * ishtp_cl_flush_queues() - Flush all queues for a client 48 + * @cl: ishtp client instance 49 + * 50 + * Used to remove all queues for a client. This is called when a client device 51 + * needs reset due to error, S3 resume or during module removal 52 + * 53 + * Return: 0 on success else -EINVAL if device is NULL 54 + */ 55 + int ishtp_cl_flush_queues(struct ishtp_cl *cl) 56 + { 57 + if (WARN_ON(!cl || !cl->dev)) 58 + return -EINVAL; 59 + 60 + ishtp_read_list_flush(cl); 61 + 62 + return 0; 63 + } 64 + EXPORT_SYMBOL(ishtp_cl_flush_queues); 65 + 66 + /** 67 + * ishtp_cl_init() - Initialize all fields of a client device 68 + * @cl: ishtp client instance 69 + * @dev: ishtp device 70 + * 71 + * Initializes a client device fields: Init spinlocks, init queues etc. 72 + * This function is called during new client creation 73 + */ 74 + static void ishtp_cl_init(struct ishtp_cl *cl, struct ishtp_device *dev) 75 + { 76 + memset(cl, 0, sizeof(struct ishtp_cl)); 77 + init_waitqueue_head(&cl->wait_ctrl_res); 78 + spin_lock_init(&cl->free_list_spinlock); 79 + spin_lock_init(&cl->in_process_spinlock); 80 + spin_lock_init(&cl->tx_list_spinlock); 81 + spin_lock_init(&cl->tx_free_list_spinlock); 82 + spin_lock_init(&cl->fc_spinlock); 83 + INIT_LIST_HEAD(&cl->link); 84 + cl->dev = dev; 85 + 86 + INIT_LIST_HEAD(&cl->free_rb_list.list); 87 + INIT_LIST_HEAD(&cl->tx_list.list); 88 + INIT_LIST_HEAD(&cl->tx_free_list.list); 89 + INIT_LIST_HEAD(&cl->in_process_list.list); 90 + 91 + cl->rx_ring_size = CL_DEF_RX_RING_SIZE; 92 + cl->tx_ring_size = CL_DEF_TX_RING_SIZE; 93 + 94 + /* dma */ 95 + cl->last_tx_path = CL_TX_PATH_IPC; 96 + cl->last_dma_acked = 1; 97 + cl->last_dma_addr = NULL; 98 + cl->last_ipc_acked = 1; 99 + } 100 + 101 + /** 102 + * ishtp_cl_allocate() - allocates client structure and sets it up. 103 + * @dev: ishtp device 104 + * 105 + * Allocate memory for new client device and call to initialize each field. 106 + * 107 + * Return: The allocated client instance or NULL on failure 108 + */ 109 + struct ishtp_cl *ishtp_cl_allocate(struct ishtp_device *dev) 110 + { 111 + struct ishtp_cl *cl; 112 + 113 + cl = kmalloc(sizeof(struct ishtp_cl), GFP_KERNEL); 114 + if (!cl) 115 + return NULL; 116 + 117 + ishtp_cl_init(cl, dev); 118 + return cl; 119 + } 120 + EXPORT_SYMBOL(ishtp_cl_allocate); 121 + 122 + /** 123 + * ishtp_cl_free() - Frees a client device 124 + * @cl: client device instance 125 + * 126 + * Frees a client device 127 + */ 128 + void ishtp_cl_free(struct ishtp_cl *cl) 129 + { 130 + struct ishtp_device *dev; 131 + unsigned long flags; 132 + 133 + if (!cl) 134 + return; 135 + 136 + dev = cl->dev; 137 + if (!dev) 138 + return; 139 + 140 + spin_lock_irqsave(&dev->cl_list_lock, flags); 141 + ishtp_cl_free_rx_ring(cl); 142 + ishtp_cl_free_tx_ring(cl); 143 + kfree(cl); 144 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 145 + } 146 + EXPORT_SYMBOL(ishtp_cl_free); 147 + 148 + /** 149 + * ishtp_cl_link() - Reserve a host id and link the client instance 150 + * @cl: client device instance 151 + * @id: host client id to use. It can be ISHTP_HOST_CLIENT_ID_ANY if any 152 + * id from the available can be used 153 + * 154 + * 155 + * This allocates a single bit in the hostmap. This function will make sure 156 + * that not many client sessions are opened at the same time. Once allocated 157 + * the client device instance is added to the ishtp device in the current 158 + * client list 159 + * 160 + * Return: 0 or error code on failure 161 + */ 162 + int ishtp_cl_link(struct ishtp_cl *cl, int id) 163 + { 164 + struct ishtp_device *dev; 165 + unsigned long flags, flags_cl; 166 + int ret = 0; 167 + 168 + if (WARN_ON(!cl || !cl->dev)) 169 + return -EINVAL; 170 + 171 + dev = cl->dev; 172 + 173 + spin_lock_irqsave(&dev->device_lock, flags); 174 + 175 + if (dev->open_handle_count >= ISHTP_MAX_OPEN_HANDLE_COUNT) { 176 + ret = -EMFILE; 177 + goto unlock_dev; 178 + } 179 + 180 + /* If Id is not assigned get one*/ 181 + if (id == ISHTP_HOST_CLIENT_ID_ANY) 182 + id = find_first_zero_bit(dev->host_clients_map, 183 + ISHTP_CLIENTS_MAX); 184 + 185 + if (id >= ISHTP_CLIENTS_MAX) { 186 + spin_unlock_irqrestore(&dev->device_lock, flags); 187 + dev_err(&cl->device->dev, "id exceeded %d", ISHTP_CLIENTS_MAX); 188 + return -ENOENT; 189 + } 190 + 191 + dev->open_handle_count++; 192 + cl->host_client_id = id; 193 + spin_lock_irqsave(&dev->cl_list_lock, flags_cl); 194 + if (dev->dev_state != ISHTP_DEV_ENABLED) { 195 + ret = -ENODEV; 196 + goto unlock_cl; 197 + } 198 + list_add_tail(&cl->link, &dev->cl_list); 199 + set_bit(id, dev->host_clients_map); 200 + cl->state = ISHTP_CL_INITIALIZING; 201 + 202 + unlock_cl: 203 + spin_unlock_irqrestore(&dev->cl_list_lock, flags_cl); 204 + unlock_dev: 205 + spin_unlock_irqrestore(&dev->device_lock, flags); 206 + return ret; 207 + } 208 + EXPORT_SYMBOL(ishtp_cl_link); 209 + 210 + /** 211 + * ishtp_cl_unlink() - remove fw_cl from the client device list 212 + * @cl: client device instance 213 + * 214 + * Remove a previously linked device to a ishtp device 215 + */ 216 + void ishtp_cl_unlink(struct ishtp_cl *cl) 217 + { 218 + struct ishtp_device *dev; 219 + struct ishtp_cl *pos; 220 + unsigned long flags; 221 + 222 + /* don't shout on error exit path */ 223 + if (!cl || !cl->dev) 224 + return; 225 + 226 + dev = cl->dev; 227 + 228 + spin_lock_irqsave(&dev->device_lock, flags); 229 + if (dev->open_handle_count > 0) { 230 + clear_bit(cl->host_client_id, dev->host_clients_map); 231 + dev->open_handle_count--; 232 + } 233 + spin_unlock_irqrestore(&dev->device_lock, flags); 234 + 235 + /* 236 + * This checks that 'cl' is actually linked into device's structure, 237 + * before attempting 'list_del' 238 + */ 239 + spin_lock_irqsave(&dev->cl_list_lock, flags); 240 + list_for_each_entry(pos, &dev->cl_list, link) 241 + if (cl->host_client_id == pos->host_client_id) { 242 + list_del_init(&pos->link); 243 + break; 244 + } 245 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 246 + } 247 + EXPORT_SYMBOL(ishtp_cl_unlink); 248 + 249 + /** 250 + * ishtp_cl_disconnect() - Send disconnect request to firmware 251 + * @cl: client device instance 252 + * 253 + * Send a disconnect request for a client to firmware. 254 + * 255 + * Return: 0 if successful disconnect response from the firmware or error 256 + * code on failure 257 + */ 258 + int ishtp_cl_disconnect(struct ishtp_cl *cl) 259 + { 260 + struct ishtp_device *dev; 261 + int err; 262 + 263 + if (WARN_ON(!cl || !cl->dev)) 264 + return -ENODEV; 265 + 266 + dev = cl->dev; 267 + 268 + dev->print_log(dev, "%s() state %d\n", __func__, cl->state); 269 + 270 + if (cl->state != ISHTP_CL_DISCONNECTING) { 271 + dev->print_log(dev, "%s() Disconnect in progress\n", __func__); 272 + return 0; 273 + } 274 + 275 + if (ishtp_hbm_cl_disconnect_req(dev, cl)) { 276 + dev->print_log(dev, "%s() Failed to disconnect\n", __func__); 277 + dev_err(&cl->device->dev, "failed to disconnect.\n"); 278 + return -ENODEV; 279 + } 280 + 281 + err = wait_event_interruptible_timeout(cl->wait_ctrl_res, 282 + (dev->dev_state != ISHTP_DEV_ENABLED || 283 + cl->state == ISHTP_CL_DISCONNECTED), 284 + ishtp_secs_to_jiffies(ISHTP_CL_CONNECT_TIMEOUT)); 285 + 286 + /* 287 + * If FW reset arrived, this will happen. Don't check cl->, 288 + * as 'cl' may be freed already 289 + */ 290 + if (dev->dev_state != ISHTP_DEV_ENABLED) { 291 + dev->print_log(dev, "%s() dev_state != ISHTP_DEV_ENABLED\n", 292 + __func__); 293 + return -ENODEV; 294 + } 295 + 296 + if (cl->state == ISHTP_CL_DISCONNECTED) { 297 + dev->print_log(dev, "%s() successful\n", __func__); 298 + return 0; 299 + } 300 + 301 + return -ENODEV; 302 + } 303 + EXPORT_SYMBOL(ishtp_cl_disconnect); 304 + 305 + /** 306 + * ishtp_cl_is_other_connecting() - Check other client is connecting 307 + * @cl: client device instance 308 + * 309 + * Checks if other client with the same fw client id is connecting 310 + * 311 + * Return: true if other client is connected else false 312 + */ 313 + static bool ishtp_cl_is_other_connecting(struct ishtp_cl *cl) 314 + { 315 + struct ishtp_device *dev; 316 + struct ishtp_cl *pos; 317 + unsigned long flags; 318 + 319 + if (WARN_ON(!cl || !cl->dev)) 320 + return false; 321 + 322 + dev = cl->dev; 323 + spin_lock_irqsave(&dev->cl_list_lock, flags); 324 + list_for_each_entry(pos, &dev->cl_list, link) { 325 + if ((pos->state == ISHTP_CL_CONNECTING) && (pos != cl) && 326 + cl->fw_client_id == pos->fw_client_id) { 327 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 328 + return true; 329 + } 330 + } 331 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 332 + 333 + return false; 334 + } 335 + 336 + /** 337 + * ishtp_cl_connect() - Send connect request to firmware 338 + * @cl: client device instance 339 + * 340 + * Send a connect request for a client to firmware. If successful it will 341 + * RX and TX ring buffers 342 + * 343 + * Return: 0 if successful connect response from the firmware and able 344 + * to bind and allocate ring buffers or error code on failure 345 + */ 346 + int ishtp_cl_connect(struct ishtp_cl *cl) 347 + { 348 + struct ishtp_device *dev; 349 + int rets; 350 + 351 + if (WARN_ON(!cl || !cl->dev)) 352 + return -ENODEV; 353 + 354 + dev = cl->dev; 355 + 356 + dev->print_log(dev, "%s() current_state = %d\n", __func__, cl->state); 357 + 358 + if (ishtp_cl_is_other_connecting(cl)) { 359 + dev->print_log(dev, "%s() Busy\n", __func__); 360 + return -EBUSY; 361 + } 362 + 363 + if (ishtp_hbm_cl_connect_req(dev, cl)) { 364 + dev->print_log(dev, "%s() HBM connect req fail\n", __func__); 365 + return -ENODEV; 366 + } 367 + 368 + rets = wait_event_interruptible_timeout(cl->wait_ctrl_res, 369 + (dev->dev_state == ISHTP_DEV_ENABLED && 370 + (cl->state == ISHTP_CL_CONNECTED || 371 + cl->state == ISHTP_CL_DISCONNECTED)), 372 + ishtp_secs_to_jiffies( 373 + ISHTP_CL_CONNECT_TIMEOUT)); 374 + /* 375 + * If FW reset arrived, this will happen. Don't check cl->, 376 + * as 'cl' may be freed already 377 + */ 378 + if (dev->dev_state != ISHTP_DEV_ENABLED) { 379 + dev->print_log(dev, "%s() dev_state != ISHTP_DEV_ENABLED\n", 380 + __func__); 381 + return -EFAULT; 382 + } 383 + 384 + if (cl->state != ISHTP_CL_CONNECTED) { 385 + dev->print_log(dev, "%s() state != ISHTP_CL_CONNECTED\n", 386 + __func__); 387 + return -EFAULT; 388 + } 389 + 390 + rets = cl->status; 391 + if (rets) { 392 + dev->print_log(dev, "%s() Invalid status\n", __func__); 393 + return rets; 394 + } 395 + 396 + rets = ishtp_cl_device_bind(cl); 397 + if (rets) { 398 + dev->print_log(dev, "%s() Bind error\n", __func__); 399 + ishtp_cl_disconnect(cl); 400 + return rets; 401 + } 402 + 403 + rets = ishtp_cl_alloc_rx_ring(cl); 404 + if (rets) { 405 + dev->print_log(dev, "%s() Alloc RX ring failed\n", __func__); 406 + /* if failed allocation, disconnect */ 407 + ishtp_cl_disconnect(cl); 408 + return rets; 409 + } 410 + 411 + rets = ishtp_cl_alloc_tx_ring(cl); 412 + if (rets) { 413 + dev->print_log(dev, "%s() Alloc TX ring failed\n", __func__); 414 + /* if failed allocation, disconnect */ 415 + ishtp_cl_free_rx_ring(cl); 416 + ishtp_cl_disconnect(cl); 417 + return rets; 418 + } 419 + 420 + /* Upon successful connection and allocation, emit flow-control */ 421 + rets = ishtp_cl_read_start(cl); 422 + 423 + dev->print_log(dev, "%s() successful\n", __func__); 424 + 425 + return rets; 426 + } 427 + EXPORT_SYMBOL(ishtp_cl_connect); 428 + 429 + /** 430 + * ishtp_cl_read_start() - Prepare to read client message 431 + * @cl: client device instance 432 + * 433 + * Get a free buffer from pool of free read buffers and add to read buffer 434 + * pool to add contents. Send a flow control request to firmware to be able 435 + * send next message. 436 + * 437 + * Return: 0 if successful or error code on failure 438 + */ 439 + int ishtp_cl_read_start(struct ishtp_cl *cl) 440 + { 441 + struct ishtp_device *dev; 442 + struct ishtp_cl_rb *rb; 443 + int rets; 444 + int i; 445 + unsigned long flags; 446 + unsigned long dev_flags; 447 + 448 + if (WARN_ON(!cl || !cl->dev)) 449 + return -ENODEV; 450 + 451 + dev = cl->dev; 452 + 453 + if (cl->state != ISHTP_CL_CONNECTED) 454 + return -ENODEV; 455 + 456 + if (dev->dev_state != ISHTP_DEV_ENABLED) 457 + return -ENODEV; 458 + 459 + i = ishtp_fw_cl_by_id(dev, cl->fw_client_id); 460 + if (i < 0) { 461 + dev_err(&cl->device->dev, "no such fw client %d\n", 462 + cl->fw_client_id); 463 + return -ENODEV; 464 + } 465 + 466 + /* The current rb is the head of the free rb list */ 467 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 468 + if (list_empty(&cl->free_rb_list.list)) { 469 + dev_warn(&cl->device->dev, 470 + "[ishtp-ish] Rx buffers pool is empty\n"); 471 + rets = -ENOMEM; 472 + rb = NULL; 473 + spin_unlock_irqrestore(&cl->free_list_spinlock, flags); 474 + goto out; 475 + } 476 + rb = list_entry(cl->free_rb_list.list.next, struct ishtp_cl_rb, list); 477 + list_del_init(&rb->list); 478 + spin_unlock_irqrestore(&cl->free_list_spinlock, flags); 479 + 480 + rb->cl = cl; 481 + rb->buf_idx = 0; 482 + 483 + INIT_LIST_HEAD(&rb->list); 484 + rets = 0; 485 + 486 + /* 487 + * This must be BEFORE sending flow control - 488 + * response in ISR may come too fast... 489 + */ 490 + spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); 491 + list_add_tail(&rb->list, &dev->read_list.list); 492 + spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags); 493 + if (ishtp_hbm_cl_flow_control_req(dev, cl)) { 494 + rets = -ENODEV; 495 + goto out; 496 + } 497 + out: 498 + /* if ishtp_hbm_cl_flow_control_req failed, return rb to free list */ 499 + if (rets && rb) { 500 + spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); 501 + list_del(&rb->list); 502 + spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags); 503 + 504 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 505 + list_add_tail(&rb->list, &cl->free_rb_list.list); 506 + spin_unlock_irqrestore(&cl->free_list_spinlock, flags); 507 + } 508 + return rets; 509 + } 510 + 511 + /** 512 + * ishtp_cl_send() - Send a message to firmware 513 + * @cl: client device instance 514 + * @buf: message buffer 515 + * @length: length of message 516 + * 517 + * If the client is correct state to send message, this function gets a buffer 518 + * from tx ring buffers, copy the message data and call to send the message 519 + * using ishtp_cl_send_msg() 520 + * 521 + * Return: 0 if successful or error code on failure 522 + */ 523 + int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length) 524 + { 525 + struct ishtp_device *dev; 526 + int id; 527 + struct ishtp_cl_tx_ring *cl_msg; 528 + int have_msg_to_send = 0; 529 + unsigned long tx_flags, tx_free_flags; 530 + 531 + if (WARN_ON(!cl || !cl->dev)) 532 + return -ENODEV; 533 + 534 + dev = cl->dev; 535 + 536 + if (cl->state != ISHTP_CL_CONNECTED) { 537 + ++cl->err_send_msg; 538 + return -EPIPE; 539 + } 540 + 541 + if (dev->dev_state != ISHTP_DEV_ENABLED) { 542 + ++cl->err_send_msg; 543 + return -ENODEV; 544 + } 545 + 546 + /* Check if we have fw client device */ 547 + id = ishtp_fw_cl_by_id(dev, cl->fw_client_id); 548 + if (id < 0) { 549 + ++cl->err_send_msg; 550 + return -ENOENT; 551 + } 552 + 553 + if (length > dev->fw_clients[id].props.max_msg_length) { 554 + ++cl->err_send_msg; 555 + return -EMSGSIZE; 556 + } 557 + 558 + /* No free bufs */ 559 + spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); 560 + if (list_empty(&cl->tx_free_list.list)) { 561 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, 562 + tx_free_flags); 563 + ++cl->err_send_msg; 564 + return -ENOMEM; 565 + } 566 + 567 + cl_msg = list_first_entry(&cl->tx_free_list.list, 568 + struct ishtp_cl_tx_ring, list); 569 + if (!cl_msg->send_buf.data) { 570 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, 571 + tx_free_flags); 572 + return -EIO; 573 + /* Should not happen, as free list is pre-allocated */ 574 + } 575 + /* 576 + * This is safe, as 'length' is already checked for not exceeding 577 + * max ISHTP message size per client 578 + */ 579 + list_del_init(&cl_msg->list); 580 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); 581 + memcpy(cl_msg->send_buf.data, buf, length); 582 + cl_msg->send_buf.size = length; 583 + spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); 584 + have_msg_to_send = !list_empty(&cl->tx_list.list); 585 + list_add_tail(&cl_msg->list, &cl->tx_list.list); 586 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 587 + 588 + if (!have_msg_to_send && cl->ishtp_flow_ctrl_creds > 0) 589 + ishtp_cl_send_msg(dev, cl); 590 + 591 + return 0; 592 + } 593 + EXPORT_SYMBOL(ishtp_cl_send); 594 + 595 + /** 596 + * ishtp_cl_read_complete() - read complete 597 + * @rb: Pointer to client request block 598 + * 599 + * If the message is completely received call ishtp_cl_bus_rx_event() 600 + * to process message 601 + */ 602 + static void ishtp_cl_read_complete(struct ishtp_cl_rb *rb) 603 + { 604 + unsigned long flags; 605 + int schedule_work_flag = 0; 606 + struct ishtp_cl *cl = rb->cl; 607 + 608 + spin_lock_irqsave(&cl->in_process_spinlock, flags); 609 + /* 610 + * if in-process list is empty, then need to schedule 611 + * the processing thread 612 + */ 613 + schedule_work_flag = list_empty(&cl->in_process_list.list); 614 + list_add_tail(&rb->list, &cl->in_process_list.list); 615 + spin_unlock_irqrestore(&cl->in_process_spinlock, flags); 616 + 617 + if (schedule_work_flag) 618 + ishtp_cl_bus_rx_event(cl->device); 619 + } 620 + 621 + /** 622 + * ipc_tx_callback() - IPC tx callback function 623 + * @prm: Pointer to client device instance 624 + * 625 + * Send message over IPC either first time or on callback on previous message 626 + * completion 627 + */ 628 + static void ipc_tx_callback(void *prm) 629 + { 630 + struct ishtp_cl *cl = prm; 631 + struct ishtp_cl_tx_ring *cl_msg; 632 + size_t rem; 633 + struct ishtp_device *dev = (cl ? cl->dev : NULL); 634 + struct ishtp_msg_hdr ishtp_hdr; 635 + unsigned long tx_flags, tx_free_flags; 636 + unsigned char *pmsg; 637 + 638 + if (!dev) 639 + return; 640 + 641 + /* 642 + * Other conditions if some critical error has 643 + * occurred before this callback is called 644 + */ 645 + if (dev->dev_state != ISHTP_DEV_ENABLED) 646 + return; 647 + 648 + if (cl->state != ISHTP_CL_CONNECTED) 649 + return; 650 + 651 + spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); 652 + if (list_empty(&cl->tx_list.list)) { 653 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 654 + return; 655 + } 656 + 657 + if (cl->ishtp_flow_ctrl_creds != 1 && !cl->sending) { 658 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 659 + return; 660 + } 661 + 662 + if (!cl->sending) { 663 + --cl->ishtp_flow_ctrl_creds; 664 + cl->last_ipc_acked = 0; 665 + cl->last_tx_path = CL_TX_PATH_IPC; 666 + cl->sending = 1; 667 + } 668 + 669 + cl_msg = list_entry(cl->tx_list.list.next, struct ishtp_cl_tx_ring, 670 + list); 671 + rem = cl_msg->send_buf.size - cl->tx_offs; 672 + 673 + ishtp_hdr.host_addr = cl->host_client_id; 674 + ishtp_hdr.fw_addr = cl->fw_client_id; 675 + ishtp_hdr.reserved = 0; 676 + pmsg = cl_msg->send_buf.data + cl->tx_offs; 677 + 678 + if (rem <= dev->mtu) { 679 + ishtp_hdr.length = rem; 680 + ishtp_hdr.msg_complete = 1; 681 + cl->sending = 0; 682 + list_del_init(&cl_msg->list); /* Must be before write */ 683 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 684 + /* Submit to IPC queue with no callback */ 685 + ishtp_write_message(dev, &ishtp_hdr, pmsg); 686 + spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); 687 + list_add_tail(&cl_msg->list, &cl->tx_free_list.list); 688 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, 689 + tx_free_flags); 690 + } else { 691 + /* Send IPC fragment */ 692 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 693 + cl->tx_offs += dev->mtu; 694 + ishtp_hdr.length = dev->mtu; 695 + ishtp_hdr.msg_complete = 0; 696 + ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl); 697 + } 698 + } 699 + 700 + /** 701 + * ishtp_cl_send_msg_ipc() -Send message using IPC 702 + * @dev: ISHTP device instance 703 + * @cl: Pointer to client device instance 704 + * 705 + * Send message over IPC not using DMA 706 + */ 707 + static void ishtp_cl_send_msg_ipc(struct ishtp_device *dev, 708 + struct ishtp_cl *cl) 709 + { 710 + /* If last DMA message wasn't acked yet, leave this one in Tx queue */ 711 + if (cl->last_tx_path == CL_TX_PATH_DMA && cl->last_dma_acked == 0) 712 + return; 713 + 714 + cl->tx_offs = 0; 715 + ipc_tx_callback(cl); 716 + ++cl->send_msg_cnt_ipc; 717 + } 718 + 719 + /** 720 + * ishtp_cl_send_msg_dma() -Send message using DMA 721 + * @dev: ISHTP device instance 722 + * @cl: Pointer to client device instance 723 + * 724 + * Send message using DMA 725 + */ 726 + static void ishtp_cl_send_msg_dma(struct ishtp_device *dev, 727 + struct ishtp_cl *cl) 728 + { 729 + struct ishtp_msg_hdr hdr; 730 + struct dma_xfer_hbm dma_xfer; 731 + unsigned char *msg_addr; 732 + int off; 733 + struct ishtp_cl_tx_ring *cl_msg; 734 + unsigned long tx_flags, tx_free_flags; 735 + 736 + /* If last IPC message wasn't acked yet, leave this one in Tx queue */ 737 + if (cl->last_tx_path == CL_TX_PATH_IPC && cl->last_ipc_acked == 0) 738 + return; 739 + 740 + spin_lock_irqsave(&cl->tx_list_spinlock, tx_flags); 741 + if (list_empty(&cl->tx_list.list)) { 742 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 743 + return; 744 + } 745 + 746 + cl_msg = list_entry(cl->tx_list.list.next, struct ishtp_cl_tx_ring, 747 + list); 748 + 749 + msg_addr = ishtp_cl_get_dma_send_buf(dev, cl_msg->send_buf.size); 750 + if (!msg_addr) { 751 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 752 + if (dev->transfer_path == CL_TX_PATH_DEFAULT) 753 + ishtp_cl_send_msg_ipc(dev, cl); 754 + return; 755 + } 756 + 757 + list_del_init(&cl_msg->list); /* Must be before write */ 758 + spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags); 759 + 760 + --cl->ishtp_flow_ctrl_creds; 761 + cl->last_dma_acked = 0; 762 + cl->last_dma_addr = msg_addr; 763 + cl->last_tx_path = CL_TX_PATH_DMA; 764 + 765 + /* write msg to dma buf */ 766 + memcpy(msg_addr, cl_msg->send_buf.data, cl_msg->send_buf.size); 767 + 768 + /* send dma_xfer hbm msg */ 769 + off = msg_addr - (unsigned char *)dev->ishtp_host_dma_tx_buf; 770 + ishtp_hbm_hdr(&hdr, sizeof(struct dma_xfer_hbm)); 771 + dma_xfer.hbm = DMA_XFER; 772 + dma_xfer.fw_client_id = cl->fw_client_id; 773 + dma_xfer.host_client_id = cl->host_client_id; 774 + dma_xfer.reserved = 0; 775 + dma_xfer.msg_addr = dev->ishtp_host_dma_tx_buf_phys + off; 776 + dma_xfer.msg_length = cl_msg->send_buf.size; 777 + dma_xfer.reserved2 = 0; 778 + ishtp_write_message(dev, &hdr, (unsigned char *)&dma_xfer); 779 + spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags); 780 + list_add_tail(&cl_msg->list, &cl->tx_free_list.list); 781 + spin_unlock_irqrestore(&cl->tx_free_list_spinlock, tx_free_flags); 782 + ++cl->send_msg_cnt_dma; 783 + } 784 + 785 + /** 786 + * ishtp_cl_send_msg() -Send message using DMA or IPC 787 + * @dev: ISHTP device instance 788 + * @cl: Pointer to client device instance 789 + * 790 + * Send message using DMA or IPC based on transfer_path 791 + */ 792 + void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl) 793 + { 794 + if (dev->transfer_path == CL_TX_PATH_DMA) 795 + ishtp_cl_send_msg_dma(dev, cl); 796 + else 797 + ishtp_cl_send_msg_ipc(dev, cl); 798 + } 799 + 800 + /** 801 + * recv_ishtp_cl_msg() -Receive client message 802 + * @dev: ISHTP device instance 803 + * @ishtp_hdr: Pointer to message header 804 + * 805 + * Receive and dispatch ISHTP client messages. This function executes in ISR 806 + * context 807 + */ 808 + void recv_ishtp_cl_msg(struct ishtp_device *dev, 809 + struct ishtp_msg_hdr *ishtp_hdr) 810 + { 811 + struct ishtp_cl *cl; 812 + struct ishtp_cl_rb *rb; 813 + struct ishtp_cl_rb *new_rb; 814 + unsigned char *buffer = NULL; 815 + struct ishtp_cl_rb *complete_rb = NULL; 816 + unsigned long dev_flags; 817 + unsigned long flags; 818 + int rb_count; 819 + 820 + if (ishtp_hdr->reserved) { 821 + dev_err(dev->devc, "corrupted message header.\n"); 822 + goto eoi; 823 + } 824 + 825 + if (ishtp_hdr->length > IPC_PAYLOAD_SIZE) { 826 + dev_err(dev->devc, 827 + "ISHTP message length in hdr exceeds IPC MTU\n"); 828 + goto eoi; 829 + } 830 + 831 + spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); 832 + rb_count = -1; 833 + list_for_each_entry(rb, &dev->read_list.list, list) { 834 + ++rb_count; 835 + cl = rb->cl; 836 + if (!cl || !(cl->host_client_id == ishtp_hdr->host_addr && 837 + cl->fw_client_id == ishtp_hdr->fw_addr) || 838 + !(cl->state == ISHTP_CL_CONNECTED)) 839 + continue; 840 + 841 + /* If no Rx buffer is allocated, disband the rb */ 842 + if (rb->buffer.size == 0 || rb->buffer.data == NULL) { 843 + spin_unlock_irqrestore(&dev->read_list_spinlock, 844 + dev_flags); 845 + dev_err(&cl->device->dev, 846 + "Rx buffer is not allocated.\n"); 847 + list_del(&rb->list); 848 + ishtp_io_rb_free(rb); 849 + cl->status = -ENOMEM; 850 + goto eoi; 851 + } 852 + 853 + /* 854 + * If message buffer overflown (exceeds max. client msg 855 + * size, drop message and return to free buffer. 856 + * Do we need to disconnect such a client? (We don't send 857 + * back FC, so communication will be stuck anyway) 858 + */ 859 + if (rb->buffer.size < ishtp_hdr->length + rb->buf_idx) { 860 + spin_unlock_irqrestore(&dev->read_list_spinlock, 861 + dev_flags); 862 + dev_err(&cl->device->dev, 863 + "message overflow. size %d len %d idx %ld\n", 864 + rb->buffer.size, ishtp_hdr->length, 865 + rb->buf_idx); 866 + list_del(&rb->list); 867 + ishtp_cl_io_rb_recycle(rb); 868 + cl->status = -EIO; 869 + goto eoi; 870 + } 871 + 872 + buffer = rb->buffer.data + rb->buf_idx; 873 + dev->ops->ishtp_read(dev, buffer, ishtp_hdr->length); 874 + 875 + rb->buf_idx += ishtp_hdr->length; 876 + if (ishtp_hdr->msg_complete) { 877 + /* Last fragment in message - it's complete */ 878 + cl->status = 0; 879 + list_del(&rb->list); 880 + complete_rb = rb; 881 + 882 + --cl->out_flow_ctrl_creds; 883 + /* 884 + * the whole msg arrived, send a new FC, and add a new 885 + * rb buffer for the next coming msg 886 + */ 887 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 888 + 889 + if (!list_empty(&cl->free_rb_list.list)) { 890 + new_rb = list_entry(cl->free_rb_list.list.next, 891 + struct ishtp_cl_rb, list); 892 + list_del_init(&new_rb->list); 893 + spin_unlock_irqrestore(&cl->free_list_spinlock, 894 + flags); 895 + new_rb->cl = cl; 896 + new_rb->buf_idx = 0; 897 + INIT_LIST_HEAD(&new_rb->list); 898 + list_add_tail(&new_rb->list, 899 + &dev->read_list.list); 900 + 901 + ishtp_hbm_cl_flow_control_req(dev, cl); 902 + } else { 903 + spin_unlock_irqrestore(&cl->free_list_spinlock, 904 + flags); 905 + } 906 + } 907 + /* One more fragment in message (even if this was last) */ 908 + ++cl->recv_msg_num_frags; 909 + 910 + /* 911 + * We can safely break here (and in BH too), 912 + * a single input message can go only to a single request! 913 + */ 914 + break; 915 + } 916 + 917 + spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags); 918 + /* If it's nobody's message, just read and discard it */ 919 + if (!buffer) { 920 + uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE]; 921 + 922 + dev_err(dev->devc, "Dropped Rx msg - no request\n"); 923 + dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length); 924 + goto eoi; 925 + } 926 + 927 + if (complete_rb) { 928 + getnstimeofday(&cl->ts_rx); 929 + ++cl->recv_msg_cnt_ipc; 930 + ishtp_cl_read_complete(complete_rb); 931 + } 932 + eoi: 933 + return; 934 + } 935 + 936 + /** 937 + * recv_ishtp_cl_msg_dma() -Receive client message 938 + * @dev: ISHTP device instance 939 + * @msg: message pointer 940 + * @hbm: hbm buffer 941 + * 942 + * Receive and dispatch ISHTP client messages using DMA. This function executes 943 + * in ISR context 944 + */ 945 + void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, 946 + struct dma_xfer_hbm *hbm) 947 + { 948 + struct ishtp_cl *cl; 949 + struct ishtp_cl_rb *rb; 950 + struct ishtp_cl_rb *new_rb; 951 + unsigned char *buffer = NULL; 952 + struct ishtp_cl_rb *complete_rb = NULL; 953 + unsigned long dev_flags; 954 + unsigned long flags; 955 + 956 + spin_lock_irqsave(&dev->read_list_spinlock, dev_flags); 957 + list_for_each_entry(rb, &dev->read_list.list, list) { 958 + cl = rb->cl; 959 + if (!cl || !(cl->host_client_id == hbm->host_client_id && 960 + cl->fw_client_id == hbm->fw_client_id) || 961 + !(cl->state == ISHTP_CL_CONNECTED)) 962 + continue; 963 + 964 + /* 965 + * If no Rx buffer is allocated, disband the rb 966 + */ 967 + if (rb->buffer.size == 0 || rb->buffer.data == NULL) { 968 + spin_unlock_irqrestore(&dev->read_list_spinlock, 969 + dev_flags); 970 + dev_err(&cl->device->dev, 971 + "response buffer is not allocated.\n"); 972 + list_del(&rb->list); 973 + ishtp_io_rb_free(rb); 974 + cl->status = -ENOMEM; 975 + goto eoi; 976 + } 977 + 978 + /* 979 + * If message buffer overflown (exceeds max. client msg 980 + * size, drop message and return to free buffer. 981 + * Do we need to disconnect such a client? (We don't send 982 + * back FC, so communication will be stuck anyway) 983 + */ 984 + if (rb->buffer.size < hbm->msg_length) { 985 + spin_unlock_irqrestore(&dev->read_list_spinlock, 986 + dev_flags); 987 + dev_err(&cl->device->dev, 988 + "message overflow. size %d len %d idx %ld\n", 989 + rb->buffer.size, hbm->msg_length, rb->buf_idx); 990 + list_del(&rb->list); 991 + ishtp_cl_io_rb_recycle(rb); 992 + cl->status = -EIO; 993 + goto eoi; 994 + } 995 + 996 + buffer = rb->buffer.data; 997 + memcpy(buffer, msg, hbm->msg_length); 998 + rb->buf_idx = hbm->msg_length; 999 + 1000 + /* Last fragment in message - it's complete */ 1001 + cl->status = 0; 1002 + list_del(&rb->list); 1003 + complete_rb = rb; 1004 + 1005 + --cl->out_flow_ctrl_creds; 1006 + /* 1007 + * the whole msg arrived, send a new FC, and add a new 1008 + * rb buffer for the next coming msg 1009 + */ 1010 + spin_lock_irqsave(&cl->free_list_spinlock, flags); 1011 + 1012 + if (!list_empty(&cl->free_rb_list.list)) { 1013 + new_rb = list_entry(cl->free_rb_list.list.next, 1014 + struct ishtp_cl_rb, list); 1015 + list_del_init(&new_rb->list); 1016 + spin_unlock_irqrestore(&cl->free_list_spinlock, 1017 + flags); 1018 + new_rb->cl = cl; 1019 + new_rb->buf_idx = 0; 1020 + INIT_LIST_HEAD(&new_rb->list); 1021 + list_add_tail(&new_rb->list, 1022 + &dev->read_list.list); 1023 + 1024 + ishtp_hbm_cl_flow_control_req(dev, cl); 1025 + } else { 1026 + spin_unlock_irqrestore(&cl->free_list_spinlock, 1027 + flags); 1028 + } 1029 + 1030 + /* One more fragment in message (this is always last) */ 1031 + ++cl->recv_msg_num_frags; 1032 + 1033 + /* 1034 + * We can safely break here (and in BH too), 1035 + * a single input message can go only to a single request! 1036 + */ 1037 + break; 1038 + } 1039 + 1040 + spin_unlock_irqrestore(&dev->read_list_spinlock, dev_flags); 1041 + /* If it's nobody's message, just read and discard it */ 1042 + if (!buffer) { 1043 + dev_err(dev->devc, "Dropped Rx (DMA) msg - no request\n"); 1044 + goto eoi; 1045 + } 1046 + 1047 + if (complete_rb) { 1048 + getnstimeofday(&cl->ts_rx); 1049 + ++cl->recv_msg_cnt_dma; 1050 + ishtp_cl_read_complete(complete_rb); 1051 + } 1052 + eoi: 1053 + return; 1054 + }
+182
drivers/hid/intel-ish-hid/ishtp/client.h
··· 1 + /* 2 + * ISHTP client logic 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #ifndef _ISHTP_CLIENT_H_ 17 + #define _ISHTP_CLIENT_H_ 18 + 19 + #include <linux/types.h> 20 + #include "ishtp-dev.h" 21 + 22 + /* Client state */ 23 + enum cl_state { 24 + ISHTP_CL_INITIALIZING = 0, 25 + ISHTP_CL_CONNECTING, 26 + ISHTP_CL_CONNECTED, 27 + ISHTP_CL_DISCONNECTING, 28 + ISHTP_CL_DISCONNECTED 29 + }; 30 + 31 + /* Tx and Rx ring size */ 32 + #define CL_DEF_RX_RING_SIZE 2 33 + #define CL_DEF_TX_RING_SIZE 2 34 + #define CL_MAX_RX_RING_SIZE 32 35 + #define CL_MAX_TX_RING_SIZE 32 36 + 37 + #define DMA_SLOT_SIZE 4096 38 + /* Number of IPC fragments after which it's worth sending via DMA */ 39 + #define DMA_WORTH_THRESHOLD 3 40 + 41 + /* DMA/IPC Tx paths. Other the default means enforcement */ 42 + #define CL_TX_PATH_DEFAULT 0 43 + #define CL_TX_PATH_IPC 1 44 + #define CL_TX_PATH_DMA 2 45 + 46 + /* Client Tx buffer list entry */ 47 + struct ishtp_cl_tx_ring { 48 + struct list_head list; 49 + struct ishtp_msg_data send_buf; 50 + }; 51 + 52 + /* ISHTP client instance */ 53 + struct ishtp_cl { 54 + struct list_head link; 55 + struct ishtp_device *dev; 56 + enum cl_state state; 57 + int status; 58 + 59 + /* Link to ISHTP bus device */ 60 + struct ishtp_cl_device *device; 61 + 62 + /* ID of client connected */ 63 + uint8_t host_client_id; 64 + uint8_t fw_client_id; 65 + uint8_t ishtp_flow_ctrl_creds; 66 + uint8_t out_flow_ctrl_creds; 67 + 68 + /* dma */ 69 + int last_tx_path; 70 + /* 0: ack wasn't received,1:ack was received */ 71 + int last_dma_acked; 72 + unsigned char *last_dma_addr; 73 + /* 0: ack wasn't received,1:ack was received */ 74 + int last_ipc_acked; 75 + 76 + /* Rx ring buffer pool */ 77 + unsigned int rx_ring_size; 78 + struct ishtp_cl_rb free_rb_list; 79 + spinlock_t free_list_spinlock; 80 + /* Rx in-process list */ 81 + struct ishtp_cl_rb in_process_list; 82 + spinlock_t in_process_spinlock; 83 + 84 + /* Client Tx buffers list */ 85 + unsigned int tx_ring_size; 86 + struct ishtp_cl_tx_ring tx_list, tx_free_list; 87 + spinlock_t tx_list_spinlock; 88 + spinlock_t tx_free_list_spinlock; 89 + size_t tx_offs; /* Offset in buffer at head of 'tx_list' */ 90 + 91 + /** 92 + * if we get a FC, and the list is not empty, we must know whether we 93 + * are at the middle of sending. 94 + * if so -need to increase FC counter, otherwise, need to start sending 95 + * the first msg in list 96 + * (!)This is for counting-FC implementation only. Within single-FC the 97 + * other party may NOT send FC until it receives complete message 98 + */ 99 + int sending; 100 + 101 + /* Send FC spinlock */ 102 + spinlock_t fc_spinlock; 103 + 104 + /* wait queue for connect and disconnect response from FW */ 105 + wait_queue_head_t wait_ctrl_res; 106 + 107 + /* Error stats */ 108 + unsigned int err_send_msg; 109 + unsigned int err_send_fc; 110 + 111 + /* Send/recv stats */ 112 + unsigned int send_msg_cnt_ipc; 113 + unsigned int send_msg_cnt_dma; 114 + unsigned int recv_msg_cnt_ipc; 115 + unsigned int recv_msg_cnt_dma; 116 + unsigned int recv_msg_num_frags; 117 + unsigned int ishtp_flow_ctrl_cnt; 118 + unsigned int out_flow_ctrl_cnt; 119 + 120 + /* Rx msg ... out FC timing */ 121 + struct timespec ts_rx; 122 + struct timespec ts_out_fc; 123 + struct timespec ts_max_fc_delay; 124 + void *client_data; 125 + }; 126 + 127 + /* Client connection managenment internal functions */ 128 + int ishtp_can_client_connect(struct ishtp_device *ishtp_dev, uuid_le *uuid); 129 + int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id); 130 + void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl); 131 + void recv_ishtp_cl_msg(struct ishtp_device *dev, 132 + struct ishtp_msg_hdr *ishtp_hdr); 133 + int ishtp_cl_read_start(struct ishtp_cl *cl); 134 + 135 + /* Ring Buffer I/F */ 136 + int ishtp_cl_alloc_rx_ring(struct ishtp_cl *cl); 137 + int ishtp_cl_alloc_tx_ring(struct ishtp_cl *cl); 138 + void ishtp_cl_free_rx_ring(struct ishtp_cl *cl); 139 + void ishtp_cl_free_tx_ring(struct ishtp_cl *cl); 140 + 141 + /* DMA I/F functions */ 142 + void recv_ishtp_cl_msg_dma(struct ishtp_device *dev, void *msg, 143 + struct dma_xfer_hbm *hbm); 144 + void ishtp_cl_alloc_dma_buf(struct ishtp_device *dev); 145 + void ishtp_cl_free_dma_buf(struct ishtp_device *dev); 146 + void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, 147 + uint32_t size); 148 + void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, 149 + void *msg_addr, 150 + uint8_t size); 151 + 152 + /* Request blocks alloc/free I/F */ 153 + struct ishtp_cl_rb *ishtp_io_rb_init(struct ishtp_cl *cl); 154 + void ishtp_io_rb_free(struct ishtp_cl_rb *priv_rb); 155 + int ishtp_io_rb_alloc_buf(struct ishtp_cl_rb *rb, size_t length); 156 + 157 + /** 158 + * ishtp_cl_cmp_id - tells if file private data have same id 159 + * returns true - if ids are the same and not NULL 160 + */ 161 + static inline bool ishtp_cl_cmp_id(const struct ishtp_cl *cl1, 162 + const struct ishtp_cl *cl2) 163 + { 164 + return cl1 && cl2 && 165 + (cl1->host_client_id == cl2->host_client_id) && 166 + (cl1->fw_client_id == cl2->fw_client_id); 167 + } 168 + 169 + /* exported functions from ISHTP under client management scope */ 170 + struct ishtp_cl *ishtp_cl_allocate(struct ishtp_device *dev); 171 + void ishtp_cl_free(struct ishtp_cl *cl); 172 + int ishtp_cl_link(struct ishtp_cl *cl, int id); 173 + void ishtp_cl_unlink(struct ishtp_cl *cl); 174 + int ishtp_cl_disconnect(struct ishtp_cl *cl); 175 + int ishtp_cl_connect(struct ishtp_cl *cl); 176 + int ishtp_cl_send(struct ishtp_cl *cl, uint8_t *buf, size_t length); 177 + int ishtp_cl_flush_queues(struct ishtp_cl *cl); 178 + 179 + /* exported functions from ISHTP client buffer management scope */ 180 + int ishtp_cl_io_rb_recycle(struct ishtp_cl_rb *rb); 181 + 182 + #endif /* _ISHTP_CLIENT_H_ */
+175
drivers/hid/intel-ish-hid/ishtp/dma-if.c
··· 1 + /* 2 + * ISHTP DMA I/F functions 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + * 15 + */ 16 + 17 + #include <linux/slab.h> 18 + #include <linux/sched.h> 19 + #include <linux/wait.h> 20 + #include <linux/delay.h> 21 + #include <linux/dma-mapping.h> 22 + #include "ishtp-dev.h" 23 + #include "client.h" 24 + 25 + /** 26 + * ishtp_cl_alloc_dma_buf() - Allocate DMA RX and TX buffer 27 + * @dev: ishtp device 28 + * 29 + * Allocate RX and TX DMA buffer once during bus setup. 30 + * It allocates 1MB, RX and TX DMA buffer, which are divided 31 + * into slots. 32 + */ 33 + void ishtp_cl_alloc_dma_buf(struct ishtp_device *dev) 34 + { 35 + dma_addr_t h; 36 + 37 + if (dev->ishtp_host_dma_tx_buf) 38 + return; 39 + 40 + dev->ishtp_host_dma_tx_buf_size = 1024*1024; 41 + dev->ishtp_host_dma_rx_buf_size = 1024*1024; 42 + 43 + /* Allocate Tx buffer and init usage bitmap */ 44 + dev->ishtp_host_dma_tx_buf = dma_alloc_coherent(dev->devc, 45 + dev->ishtp_host_dma_tx_buf_size, 46 + &h, GFP_KERNEL); 47 + if (dev->ishtp_host_dma_tx_buf) 48 + dev->ishtp_host_dma_tx_buf_phys = h; 49 + 50 + dev->ishtp_dma_num_slots = dev->ishtp_host_dma_tx_buf_size / 51 + DMA_SLOT_SIZE; 52 + 53 + dev->ishtp_dma_tx_map = kcalloc(dev->ishtp_dma_num_slots, 54 + sizeof(uint8_t), 55 + GFP_KERNEL); 56 + spin_lock_init(&dev->ishtp_dma_tx_lock); 57 + 58 + /* Allocate Rx buffer */ 59 + dev->ishtp_host_dma_rx_buf = dma_alloc_coherent(dev->devc, 60 + dev->ishtp_host_dma_rx_buf_size, 61 + &h, GFP_KERNEL); 62 + 63 + if (dev->ishtp_host_dma_rx_buf) 64 + dev->ishtp_host_dma_rx_buf_phys = h; 65 + } 66 + 67 + /** 68 + * ishtp_cl_free_dma_buf() - Free DMA RX and TX buffer 69 + * @dev: ishtp device 70 + * 71 + * Free DMA buffer when all clients are released. This is 72 + * only happens during error path in ISH built in driver 73 + * model 74 + */ 75 + void ishtp_cl_free_dma_buf(struct ishtp_device *dev) 76 + { 77 + dma_addr_t h; 78 + 79 + if (dev->ishtp_host_dma_tx_buf) { 80 + h = dev->ishtp_host_dma_tx_buf_phys; 81 + dma_free_coherent(dev->devc, dev->ishtp_host_dma_tx_buf_size, 82 + dev->ishtp_host_dma_tx_buf, h); 83 + } 84 + 85 + if (dev->ishtp_host_dma_rx_buf) { 86 + h = dev->ishtp_host_dma_rx_buf_phys; 87 + dma_free_coherent(dev->devc, dev->ishtp_host_dma_rx_buf_size, 88 + dev->ishtp_host_dma_rx_buf, h); 89 + } 90 + 91 + kfree(dev->ishtp_dma_tx_map); 92 + dev->ishtp_host_dma_tx_buf = NULL; 93 + dev->ishtp_host_dma_rx_buf = NULL; 94 + dev->ishtp_dma_tx_map = NULL; 95 + } 96 + 97 + /* 98 + * ishtp_cl_get_dma_send_buf() - Get a DMA memory slot 99 + * @dev: ishtp device 100 + * @size: Size of memory to get 101 + * 102 + * Find and return free address of "size" bytes in dma tx buffer. 103 + * the function will mark this address as "in-used" memory. 104 + * 105 + * Return: NULL when no free buffer else a buffer to copy 106 + */ 107 + void *ishtp_cl_get_dma_send_buf(struct ishtp_device *dev, 108 + uint32_t size) 109 + { 110 + unsigned long flags; 111 + int i, j, free; 112 + /* additional slot is needed if there is rem */ 113 + int required_slots = (size / DMA_SLOT_SIZE) 114 + + 1 * (size % DMA_SLOT_SIZE != 0); 115 + 116 + spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags); 117 + for (i = 0; i <= (dev->ishtp_dma_num_slots - required_slots); i++) { 118 + free = 1; 119 + for (j = 0; j < required_slots; j++) 120 + if (dev->ishtp_dma_tx_map[i+j]) { 121 + free = 0; 122 + i += j; 123 + break; 124 + } 125 + if (free) { 126 + /* mark memory as "caught" */ 127 + for (j = 0; j < required_slots; j++) 128 + dev->ishtp_dma_tx_map[i+j] = 1; 129 + spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags); 130 + return (i * DMA_SLOT_SIZE) + 131 + (unsigned char *)dev->ishtp_host_dma_tx_buf; 132 + } 133 + } 134 + spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags); 135 + dev_err(dev->devc, "No free DMA buffer to send msg\n"); 136 + return NULL; 137 + } 138 + 139 + /* 140 + * ishtp_cl_release_dma_acked_mem() - Release DMA memory slot 141 + * @dev: ishtp device 142 + * @msg_addr: message address of slot 143 + * @size: Size of memory to get 144 + * 145 + * Release_dma_acked_mem - returnes the acked memory to free list. 146 + * (from msg_addr, size bytes long) 147 + */ 148 + void ishtp_cl_release_dma_acked_mem(struct ishtp_device *dev, 149 + void *msg_addr, 150 + uint8_t size) 151 + { 152 + unsigned long flags; 153 + int acked_slots = (size / DMA_SLOT_SIZE) 154 + + 1 * (size % DMA_SLOT_SIZE != 0); 155 + int i, j; 156 + 157 + if ((msg_addr - dev->ishtp_host_dma_tx_buf) % DMA_SLOT_SIZE) { 158 + dev_err(dev->devc, "Bad DMA Tx ack address\n"); 159 + return; 160 + } 161 + 162 + i = (msg_addr - dev->ishtp_host_dma_tx_buf) / DMA_SLOT_SIZE; 163 + spin_lock_irqsave(&dev->ishtp_dma_tx_lock, flags); 164 + for (j = 0; j < acked_slots; j++) { 165 + if ((i + j) >= dev->ishtp_dma_num_slots || 166 + !dev->ishtp_dma_tx_map[i+j]) { 167 + /* no such slot, or memory is already free */ 168 + spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags); 169 + dev_err(dev->devc, "Bad DMA Tx ack address\n"); 170 + return; 171 + } 172 + dev->ishtp_dma_tx_map[i+j] = 0; 173 + } 174 + spin_unlock_irqrestore(&dev->ishtp_dma_tx_lock, flags); 175 + }
+1032
drivers/hid/intel-ish-hid/ishtp/hbm.c
··· 1 + /* 2 + * ISHTP bus layer messages handling 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + * 15 + */ 16 + 17 + #include <linux/export.h> 18 + #include <linux/slab.h> 19 + #include <linux/sched.h> 20 + #include <linux/wait.h> 21 + #include <linux/spinlock.h> 22 + #include <linux/miscdevice.h> 23 + #include "ishtp-dev.h" 24 + #include "hbm.h" 25 + #include "client.h" 26 + 27 + /** 28 + * ishtp_hbm_fw_cl_allocate() - Allocate FW clients 29 + * @dev: ISHTP device instance 30 + * 31 + * Allocates storage for fw clients 32 + */ 33 + static void ishtp_hbm_fw_cl_allocate(struct ishtp_device *dev) 34 + { 35 + struct ishtp_fw_client *clients; 36 + int b; 37 + 38 + /* count how many ISH clients we have */ 39 + for_each_set_bit(b, dev->fw_clients_map, ISHTP_CLIENTS_MAX) 40 + dev->fw_clients_num++; 41 + 42 + if (dev->fw_clients_num <= 0) 43 + return; 44 + 45 + /* allocate storage for fw clients representation */ 46 + clients = kcalloc(dev->fw_clients_num, sizeof(struct ishtp_fw_client), 47 + GFP_KERNEL); 48 + if (!clients) { 49 + dev->dev_state = ISHTP_DEV_RESETTING; 50 + ish_hw_reset(dev); 51 + return; 52 + } 53 + dev->fw_clients = clients; 54 + } 55 + 56 + /** 57 + * ishtp_hbm_cl_hdr() - construct client hbm header 58 + * @cl: client 59 + * @hbm_cmd: host bus message command 60 + * @buf: buffer for cl header 61 + * @len: buffer length 62 + * 63 + * Initialize HBM buffer 64 + */ 65 + static inline void ishtp_hbm_cl_hdr(struct ishtp_cl *cl, uint8_t hbm_cmd, 66 + void *buf, size_t len) 67 + { 68 + struct ishtp_hbm_cl_cmd *cmd = buf; 69 + 70 + memset(cmd, 0, len); 71 + 72 + cmd->hbm_cmd = hbm_cmd; 73 + cmd->host_addr = cl->host_client_id; 74 + cmd->fw_addr = cl->fw_client_id; 75 + } 76 + 77 + /** 78 + * ishtp_hbm_cl_addr_equal() - Compare client address 79 + * @cl: client 80 + * @buf: Client command buffer 81 + * 82 + * Compare client address with the address in command buffer 83 + * 84 + * Return: True if they have the same address 85 + */ 86 + static inline bool ishtp_hbm_cl_addr_equal(struct ishtp_cl *cl, void *buf) 87 + { 88 + struct ishtp_hbm_cl_cmd *cmd = buf; 89 + 90 + return cl->host_client_id == cmd->host_addr && 91 + cl->fw_client_id == cmd->fw_addr; 92 + } 93 + 94 + /** 95 + * ishtp_hbm_start_wait() - Wait for HBM start message 96 + * @dev: ISHTP device instance 97 + * 98 + * Wait for HBM start message from firmware 99 + * 100 + * Return: 0 if HBM start is/was received else timeout error 101 + */ 102 + int ishtp_hbm_start_wait(struct ishtp_device *dev) 103 + { 104 + int ret; 105 + 106 + if (dev->hbm_state > ISHTP_HBM_START) 107 + return 0; 108 + 109 + dev_dbg(dev->devc, "Going to wait for ishtp start. hbm_state=%08X\n", 110 + dev->hbm_state); 111 + ret = wait_event_interruptible_timeout(dev->wait_hbm_recvd_msg, 112 + dev->hbm_state >= ISHTP_HBM_STARTED, 113 + (ISHTP_INTEROP_TIMEOUT * HZ)); 114 + 115 + dev_dbg(dev->devc, 116 + "Woke up from waiting for ishtp start. hbm_state=%08X\n", 117 + dev->hbm_state); 118 + 119 + if (ret <= 0 && (dev->hbm_state <= ISHTP_HBM_START)) { 120 + dev->hbm_state = ISHTP_HBM_IDLE; 121 + dev_err(dev->devc, 122 + "waiting for ishtp start failed. ret=%d hbm_state=%08X\n", 123 + ret, dev->hbm_state); 124 + return -ETIMEDOUT; 125 + } 126 + return 0; 127 + } 128 + 129 + /** 130 + * ishtp_hbm_start_req() - Send HBM start message 131 + * @dev: ISHTP device instance 132 + * 133 + * Send HBM start message to firmware 134 + * 135 + * Return: 0 if success else error code 136 + */ 137 + int ishtp_hbm_start_req(struct ishtp_device *dev) 138 + { 139 + struct ishtp_msg_hdr hdr; 140 + unsigned char data[128]; 141 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 142 + struct hbm_host_version_request *start_req; 143 + const size_t len = sizeof(struct hbm_host_version_request); 144 + 145 + ishtp_hbm_hdr(ishtp_hdr, len); 146 + 147 + /* host start message */ 148 + start_req = (struct hbm_host_version_request *)data; 149 + memset(start_req, 0, len); 150 + start_req->hbm_cmd = HOST_START_REQ_CMD; 151 + start_req->host_version.major_version = HBM_MAJOR_VERSION; 152 + start_req->host_version.minor_version = HBM_MINOR_VERSION; 153 + 154 + /* 155 + * (!) Response to HBM start may be so quick that this thread would get 156 + * preempted BEFORE managing to set hbm_state = ISHTP_HBM_START. 157 + * So set it at first, change back to ISHTP_HBM_IDLE upon failure 158 + */ 159 + dev->hbm_state = ISHTP_HBM_START; 160 + if (ishtp_write_message(dev, ishtp_hdr, data)) { 161 + dev_err(dev->devc, "version message send failed\n"); 162 + dev->dev_state = ISHTP_DEV_RESETTING; 163 + dev->hbm_state = ISHTP_HBM_IDLE; 164 + ish_hw_reset(dev); 165 + return -ENODEV; 166 + } 167 + 168 + return 0; 169 + } 170 + 171 + /** 172 + * ishtp_hbm_enum_clients_req() - Send client enum req 173 + * @dev: ISHTP device instance 174 + * 175 + * Send enumeration client request message 176 + * 177 + * Return: 0 if success else error code 178 + */ 179 + void ishtp_hbm_enum_clients_req(struct ishtp_device *dev) 180 + { 181 + struct ishtp_msg_hdr hdr; 182 + unsigned char data[128]; 183 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 184 + struct hbm_host_enum_request *enum_req; 185 + const size_t len = sizeof(struct hbm_host_enum_request); 186 + 187 + /* enumerate clients */ 188 + ishtp_hbm_hdr(ishtp_hdr, len); 189 + 190 + enum_req = (struct hbm_host_enum_request *)data; 191 + memset(enum_req, 0, len); 192 + enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; 193 + 194 + if (ishtp_write_message(dev, ishtp_hdr, data)) { 195 + dev->dev_state = ISHTP_DEV_RESETTING; 196 + dev_err(dev->devc, "enumeration request send failed\n"); 197 + ish_hw_reset(dev); 198 + } 199 + dev->hbm_state = ISHTP_HBM_ENUM_CLIENTS; 200 + } 201 + 202 + /** 203 + * ishtp_hbm_prop_req() - Request property 204 + * @dev: ISHTP device instance 205 + * 206 + * Request property for a single client 207 + * 208 + * Return: 0 if success else error code 209 + */ 210 + static int ishtp_hbm_prop_req(struct ishtp_device *dev) 211 + { 212 + 213 + struct ishtp_msg_hdr hdr; 214 + unsigned char data[128]; 215 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 216 + struct hbm_props_request *prop_req; 217 + const size_t len = sizeof(struct hbm_props_request); 218 + unsigned long next_client_index; 219 + uint8_t client_num; 220 + 221 + client_num = dev->fw_client_presentation_num; 222 + 223 + next_client_index = find_next_bit(dev->fw_clients_map, 224 + ISHTP_CLIENTS_MAX, dev->fw_client_index); 225 + 226 + /* We got all client properties */ 227 + if (next_client_index == ISHTP_CLIENTS_MAX) { 228 + dev->hbm_state = ISHTP_HBM_WORKING; 229 + dev->dev_state = ISHTP_DEV_ENABLED; 230 + 231 + for (dev->fw_client_presentation_num = 1; 232 + dev->fw_client_presentation_num < client_num + 1; 233 + ++dev->fw_client_presentation_num) 234 + /* Add new client device */ 235 + ishtp_bus_new_client(dev); 236 + return 0; 237 + } 238 + 239 + dev->fw_clients[client_num].client_id = next_client_index; 240 + 241 + ishtp_hbm_hdr(ishtp_hdr, len); 242 + prop_req = (struct hbm_props_request *)data; 243 + 244 + memset(prop_req, 0, sizeof(struct hbm_props_request)); 245 + 246 + prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; 247 + prop_req->address = next_client_index; 248 + 249 + if (ishtp_write_message(dev, ishtp_hdr, data)) { 250 + dev->dev_state = ISHTP_DEV_RESETTING; 251 + dev_err(dev->devc, "properties request send failed\n"); 252 + ish_hw_reset(dev); 253 + return -EIO; 254 + } 255 + 256 + dev->fw_client_index = next_client_index; 257 + 258 + return 0; 259 + } 260 + 261 + /** 262 + * ishtp_hbm_stop_req() - Send HBM stop 263 + * @dev: ISHTP device instance 264 + * 265 + * Send stop request message 266 + */ 267 + static void ishtp_hbm_stop_req(struct ishtp_device *dev) 268 + { 269 + struct ishtp_msg_hdr hdr; 270 + unsigned char data[128]; 271 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 272 + struct hbm_host_stop_request *req; 273 + const size_t len = sizeof(struct hbm_host_stop_request); 274 + 275 + ishtp_hbm_hdr(ishtp_hdr, len); 276 + req = (struct hbm_host_stop_request *)data; 277 + 278 + memset(req, 0, sizeof(struct hbm_host_stop_request)); 279 + req->hbm_cmd = HOST_STOP_REQ_CMD; 280 + req->reason = DRIVER_STOP_REQUEST; 281 + 282 + ishtp_write_message(dev, ishtp_hdr, data); 283 + } 284 + 285 + /** 286 + * ishtp_hbm_cl_flow_control_req() - Send flow control request 287 + * @dev: ISHTP device instance 288 + * @cl: ISHTP client instance 289 + * 290 + * Send flow control request 291 + * 292 + * Return: 0 if success else error code 293 + */ 294 + int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev, 295 + struct ishtp_cl *cl) 296 + { 297 + struct ishtp_msg_hdr hdr; 298 + unsigned char data[128]; 299 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 300 + const size_t len = sizeof(struct hbm_flow_control); 301 + int rv; 302 + unsigned int num_frags; 303 + unsigned long flags; 304 + 305 + spin_lock_irqsave(&cl->fc_spinlock, flags); 306 + ishtp_hbm_hdr(ishtp_hdr, len); 307 + ishtp_hbm_cl_hdr(cl, ISHTP_FLOW_CONTROL_CMD, data, len); 308 + 309 + /* 310 + * Sync possible race when RB recycle and packet receive paths 311 + * both try to send an out FC 312 + */ 313 + if (cl->out_flow_ctrl_creds) { 314 + spin_unlock_irqrestore(&cl->fc_spinlock, flags); 315 + return 0; 316 + } 317 + 318 + num_frags = cl->recv_msg_num_frags; 319 + cl->recv_msg_num_frags = 0; 320 + 321 + rv = ishtp_write_message(dev, ishtp_hdr, data); 322 + if (!rv) { 323 + ++cl->out_flow_ctrl_creds; 324 + ++cl->out_flow_ctrl_cnt; 325 + getnstimeofday(&cl->ts_out_fc); 326 + if (cl->ts_rx.tv_sec && cl->ts_rx.tv_nsec) { 327 + struct timespec ts_diff; 328 + 329 + ts_diff = timespec_sub(cl->ts_out_fc, cl->ts_rx); 330 + if (timespec_compare(&ts_diff, &cl->ts_max_fc_delay) 331 + > 0) 332 + cl->ts_max_fc_delay = ts_diff; 333 + } 334 + } else { 335 + ++cl->err_send_fc; 336 + } 337 + 338 + spin_unlock_irqrestore(&cl->fc_spinlock, flags); 339 + return rv; 340 + } 341 + 342 + /** 343 + * ishtp_hbm_cl_disconnect_req() - Send disconnect request 344 + * @dev: ISHTP device instance 345 + * @cl: ISHTP client instance 346 + * 347 + * Send disconnect message to fw 348 + * 349 + * Return: 0 if success else error code 350 + */ 351 + int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl) 352 + { 353 + struct ishtp_msg_hdr hdr; 354 + unsigned char data[128]; 355 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 356 + const size_t len = sizeof(struct hbm_client_connect_request); 357 + 358 + ishtp_hbm_hdr(ishtp_hdr, len); 359 + ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_REQ_CMD, data, len); 360 + 361 + return ishtp_write_message(dev, ishtp_hdr, data); 362 + } 363 + 364 + /** 365 + * ishtp_hbm_cl_disconnect_res() - Get disconnect response 366 + * @dev: ISHTP device instance 367 + * @rs: Response message 368 + * 369 + * Received disconnect response from fw 370 + */ 371 + static void ishtp_hbm_cl_disconnect_res(struct ishtp_device *dev, 372 + struct hbm_client_connect_response *rs) 373 + { 374 + struct ishtp_cl *cl = NULL; 375 + unsigned long flags; 376 + 377 + spin_lock_irqsave(&dev->cl_list_lock, flags); 378 + list_for_each_entry(cl, &dev->cl_list, link) { 379 + if (!rs->status && ishtp_hbm_cl_addr_equal(cl, rs)) { 380 + cl->state = ISHTP_CL_DISCONNECTED; 381 + break; 382 + } 383 + } 384 + if (cl) 385 + wake_up_interruptible(&cl->wait_ctrl_res); 386 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 387 + } 388 + 389 + /** 390 + * ishtp_hbm_cl_connect_req() - Send connect request 391 + * @dev: ISHTP device instance 392 + * @cl: client device instance 393 + * 394 + * Send connection request to specific fw client 395 + * 396 + * Return: 0 if success else error code 397 + */ 398 + int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl) 399 + { 400 + struct ishtp_msg_hdr hdr; 401 + unsigned char data[128]; 402 + struct ishtp_msg_hdr *ishtp_hdr = &hdr; 403 + const size_t len = sizeof(struct hbm_client_connect_request); 404 + 405 + ishtp_hbm_hdr(ishtp_hdr, len); 406 + ishtp_hbm_cl_hdr(cl, CLIENT_CONNECT_REQ_CMD, data, len); 407 + 408 + return ishtp_write_message(dev, ishtp_hdr, data); 409 + } 410 + 411 + /** 412 + * ishtp_hbm_cl_connect_res() - Get connect response 413 + * @dev: ISHTP device instance 414 + * @rs: Response message 415 + * 416 + * Received connect response from fw 417 + */ 418 + static void ishtp_hbm_cl_connect_res(struct ishtp_device *dev, 419 + struct hbm_client_connect_response *rs) 420 + { 421 + struct ishtp_cl *cl = NULL; 422 + unsigned long flags; 423 + 424 + spin_lock_irqsave(&dev->cl_list_lock, flags); 425 + list_for_each_entry(cl, &dev->cl_list, link) { 426 + if (ishtp_hbm_cl_addr_equal(cl, rs)) { 427 + if (!rs->status) { 428 + cl->state = ISHTP_CL_CONNECTED; 429 + cl->status = 0; 430 + } else { 431 + cl->state = ISHTP_CL_DISCONNECTED; 432 + cl->status = -ENODEV; 433 + } 434 + break; 435 + } 436 + } 437 + if (cl) 438 + wake_up_interruptible(&cl->wait_ctrl_res); 439 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 440 + } 441 + 442 + /** 443 + * ishtp_client_disconnect_request() - Receive disconnect request 444 + * @dev: ISHTP device instance 445 + * @disconnect_req: disconnect request structure 446 + * 447 + * Disconnect request bus message from the fw. Send diconnect response. 448 + */ 449 + static void ishtp_hbm_fw_disconnect_req(struct ishtp_device *dev, 450 + struct hbm_client_connect_request *disconnect_req) 451 + { 452 + struct ishtp_cl *cl; 453 + const size_t len = sizeof(struct hbm_client_connect_response); 454 + unsigned long flags; 455 + struct ishtp_msg_hdr hdr; 456 + unsigned char data[4]; /* All HBM messages are 4 bytes */ 457 + 458 + spin_lock_irqsave(&dev->cl_list_lock, flags); 459 + list_for_each_entry(cl, &dev->cl_list, link) { 460 + if (ishtp_hbm_cl_addr_equal(cl, disconnect_req)) { 461 + cl->state = ISHTP_CL_DISCONNECTED; 462 + 463 + /* send disconnect response */ 464 + ishtp_hbm_hdr(&hdr, len); 465 + ishtp_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, data, 466 + len); 467 + ishtp_write_message(dev, &hdr, data); 468 + break; 469 + } 470 + } 471 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 472 + } 473 + 474 + /** 475 + * ishtp_hbm_dma_xfer_ack(() - Receive transfer ACK 476 + * @dev: ISHTP device instance 477 + * @dma_xfer: HBM transfer message 478 + * 479 + * Receive ack for ISHTP-over-DMA client message 480 + */ 481 + static void ishtp_hbm_dma_xfer_ack(struct ishtp_device *dev, 482 + struct dma_xfer_hbm *dma_xfer) 483 + { 484 + void *msg; 485 + uint64_t offs; 486 + struct ishtp_msg_hdr *ishtp_hdr = 487 + (struct ishtp_msg_hdr *)&dev->ishtp_msg_hdr; 488 + unsigned int msg_offs; 489 + struct ishtp_cl *cl; 490 + 491 + for (msg_offs = 0; msg_offs < ishtp_hdr->length; 492 + msg_offs += sizeof(struct dma_xfer_hbm)) { 493 + offs = dma_xfer->msg_addr - dev->ishtp_host_dma_tx_buf_phys; 494 + if (offs > dev->ishtp_host_dma_tx_buf_size) { 495 + dev_err(dev->devc, "Bad DMA Tx ack message address\n"); 496 + return; 497 + } 498 + if (dma_xfer->msg_length > 499 + dev->ishtp_host_dma_tx_buf_size - offs) { 500 + dev_err(dev->devc, "Bad DMA Tx ack message size\n"); 501 + return; 502 + } 503 + 504 + /* logical address of the acked mem */ 505 + msg = (unsigned char *)dev->ishtp_host_dma_tx_buf + offs; 506 + ishtp_cl_release_dma_acked_mem(dev, msg, dma_xfer->msg_length); 507 + 508 + list_for_each_entry(cl, &dev->cl_list, link) { 509 + if (cl->fw_client_id == dma_xfer->fw_client_id && 510 + cl->host_client_id == dma_xfer->host_client_id) 511 + /* 512 + * in case that a single ack may be sent 513 + * over several dma transfers, and the last msg 514 + * addr was inside the acked memory, but not in 515 + * its start 516 + */ 517 + if (cl->last_dma_addr >= 518 + (unsigned char *)msg && 519 + cl->last_dma_addr < 520 + (unsigned char *)msg + 521 + dma_xfer->msg_length) { 522 + cl->last_dma_acked = 1; 523 + 524 + if (!list_empty(&cl->tx_list.list) && 525 + cl->ishtp_flow_ctrl_creds) { 526 + /* 527 + * start sending the first msg 528 + */ 529 + ishtp_cl_send_msg(dev, cl); 530 + } 531 + } 532 + } 533 + ++dma_xfer; 534 + } 535 + } 536 + 537 + /** 538 + * ishtp_hbm_dma_xfer() - Receive DMA transfer message 539 + * @dev: ISHTP device instance 540 + * @dma_xfer: HBM transfer message 541 + * 542 + * Receive ISHTP-over-DMA client message 543 + */ 544 + static void ishtp_hbm_dma_xfer(struct ishtp_device *dev, 545 + struct dma_xfer_hbm *dma_xfer) 546 + { 547 + void *msg; 548 + uint64_t offs; 549 + struct ishtp_msg_hdr hdr; 550 + struct ishtp_msg_hdr *ishtp_hdr = 551 + (struct ishtp_msg_hdr *) &dev->ishtp_msg_hdr; 552 + struct dma_xfer_hbm *prm = dma_xfer; 553 + unsigned int msg_offs; 554 + 555 + for (msg_offs = 0; msg_offs < ishtp_hdr->length; 556 + msg_offs += sizeof(struct dma_xfer_hbm)) { 557 + 558 + offs = dma_xfer->msg_addr - dev->ishtp_host_dma_rx_buf_phys; 559 + if (offs > dev->ishtp_host_dma_rx_buf_size) { 560 + dev_err(dev->devc, "Bad DMA Rx message address\n"); 561 + return; 562 + } 563 + if (dma_xfer->msg_length > 564 + dev->ishtp_host_dma_rx_buf_size - offs) { 565 + dev_err(dev->devc, "Bad DMA Rx message size\n"); 566 + return; 567 + } 568 + msg = dev->ishtp_host_dma_rx_buf + offs; 569 + recv_ishtp_cl_msg_dma(dev, msg, dma_xfer); 570 + dma_xfer->hbm = DMA_XFER_ACK; /* Prepare for response */ 571 + ++dma_xfer; 572 + } 573 + 574 + /* Send DMA_XFER_ACK [...] */ 575 + ishtp_hbm_hdr(&hdr, ishtp_hdr->length); 576 + ishtp_write_message(dev, &hdr, (unsigned char *)prm); 577 + } 578 + 579 + /** 580 + * ishtp_hbm_dispatch() - HBM dispatch function 581 + * @dev: ISHTP device instance 582 + * @hdr: bus message 583 + * 584 + * Bottom half read routine after ISR to handle the read bus message cmd 585 + * processing 586 + */ 587 + void ishtp_hbm_dispatch(struct ishtp_device *dev, 588 + struct ishtp_bus_message *hdr) 589 + { 590 + struct ishtp_bus_message *ishtp_msg; 591 + struct ishtp_fw_client *fw_client; 592 + struct hbm_host_version_response *version_res; 593 + struct hbm_client_connect_response *connect_res; 594 + struct hbm_client_connect_response *disconnect_res; 595 + struct hbm_client_connect_request *disconnect_req; 596 + struct hbm_props_response *props_res; 597 + struct hbm_host_enum_response *enum_res; 598 + struct ishtp_msg_hdr ishtp_hdr; 599 + struct dma_alloc_notify dma_alloc_notify; 600 + struct dma_xfer_hbm *dma_xfer; 601 + 602 + ishtp_msg = hdr; 603 + 604 + switch (ishtp_msg->hbm_cmd) { 605 + case HOST_START_RES_CMD: 606 + version_res = (struct hbm_host_version_response *)ishtp_msg; 607 + if (!version_res->host_version_supported) { 608 + dev->version = version_res->fw_max_version; 609 + 610 + dev->hbm_state = ISHTP_HBM_STOPPED; 611 + ishtp_hbm_stop_req(dev); 612 + return; 613 + } 614 + 615 + dev->version.major_version = HBM_MAJOR_VERSION; 616 + dev->version.minor_version = HBM_MINOR_VERSION; 617 + if (dev->dev_state == ISHTP_DEV_INIT_CLIENTS && 618 + dev->hbm_state == ISHTP_HBM_START) { 619 + dev->hbm_state = ISHTP_HBM_STARTED; 620 + ishtp_hbm_enum_clients_req(dev); 621 + } else { 622 + dev_err(dev->devc, 623 + "reset: wrong host start response\n"); 624 + /* BUG: why do we arrive here? */ 625 + ish_hw_reset(dev); 626 + return; 627 + } 628 + 629 + wake_up_interruptible(&dev->wait_hbm_recvd_msg); 630 + break; 631 + 632 + case CLIENT_CONNECT_RES_CMD: 633 + connect_res = (struct hbm_client_connect_response *)ishtp_msg; 634 + ishtp_hbm_cl_connect_res(dev, connect_res); 635 + break; 636 + 637 + case CLIENT_DISCONNECT_RES_CMD: 638 + disconnect_res = 639 + (struct hbm_client_connect_response *)ishtp_msg; 640 + ishtp_hbm_cl_disconnect_res(dev, disconnect_res); 641 + break; 642 + 643 + case HOST_CLIENT_PROPERTIES_RES_CMD: 644 + props_res = (struct hbm_props_response *)ishtp_msg; 645 + fw_client = &dev->fw_clients[dev->fw_client_presentation_num]; 646 + 647 + if (props_res->status || !dev->fw_clients) { 648 + dev_err(dev->devc, 649 + "reset: properties response hbm wrong status\n"); 650 + ish_hw_reset(dev); 651 + return; 652 + } 653 + 654 + if (fw_client->client_id != props_res->address) { 655 + dev_err(dev->devc, 656 + "reset: host properties response address mismatch [%02X %02X]\n", 657 + fw_client->client_id, props_res->address); 658 + ish_hw_reset(dev); 659 + return; 660 + } 661 + 662 + if (dev->dev_state != ISHTP_DEV_INIT_CLIENTS || 663 + dev->hbm_state != ISHTP_HBM_CLIENT_PROPERTIES) { 664 + dev_err(dev->devc, 665 + "reset: unexpected properties response\n"); 666 + ish_hw_reset(dev); 667 + return; 668 + } 669 + 670 + fw_client->props = props_res->client_properties; 671 + dev->fw_client_index++; 672 + dev->fw_client_presentation_num++; 673 + 674 + /* request property for the next client */ 675 + ishtp_hbm_prop_req(dev); 676 + 677 + if (dev->dev_state != ISHTP_DEV_ENABLED) 678 + break; 679 + 680 + if (!ishtp_use_dma_transfer()) 681 + break; 682 + 683 + dev_dbg(dev->devc, "Requesting to use DMA\n"); 684 + ishtp_cl_alloc_dma_buf(dev); 685 + if (dev->ishtp_host_dma_rx_buf) { 686 + const size_t len = sizeof(dma_alloc_notify); 687 + 688 + memset(&dma_alloc_notify, 0, sizeof(dma_alloc_notify)); 689 + dma_alloc_notify.hbm = DMA_BUFFER_ALLOC_NOTIFY; 690 + dma_alloc_notify.buf_size = 691 + dev->ishtp_host_dma_rx_buf_size; 692 + dma_alloc_notify.buf_address = 693 + dev->ishtp_host_dma_rx_buf_phys; 694 + ishtp_hbm_hdr(&ishtp_hdr, len); 695 + ishtp_write_message(dev, &ishtp_hdr, 696 + (unsigned char *)&dma_alloc_notify); 697 + } 698 + 699 + break; 700 + 701 + case HOST_ENUM_RES_CMD: 702 + enum_res = (struct hbm_host_enum_response *) ishtp_msg; 703 + memcpy(dev->fw_clients_map, enum_res->valid_addresses, 32); 704 + if (dev->dev_state == ISHTP_DEV_INIT_CLIENTS && 705 + dev->hbm_state == ISHTP_HBM_ENUM_CLIENTS) { 706 + dev->fw_client_presentation_num = 0; 707 + dev->fw_client_index = 0; 708 + 709 + ishtp_hbm_fw_cl_allocate(dev); 710 + dev->hbm_state = ISHTP_HBM_CLIENT_PROPERTIES; 711 + 712 + /* first property request */ 713 + ishtp_hbm_prop_req(dev); 714 + } else { 715 + dev_err(dev->devc, 716 + "reset: unexpected enumeration response hbm\n"); 717 + ish_hw_reset(dev); 718 + return; 719 + } 720 + break; 721 + 722 + case HOST_STOP_RES_CMD: 723 + if (dev->hbm_state != ISHTP_HBM_STOPPED) 724 + dev_err(dev->devc, "unexpected stop response\n"); 725 + 726 + dev->dev_state = ISHTP_DEV_DISABLED; 727 + dev_info(dev->devc, "reset: FW stop response\n"); 728 + ish_hw_reset(dev); 729 + break; 730 + 731 + case CLIENT_DISCONNECT_REQ_CMD: 732 + /* search for client */ 733 + disconnect_req = 734 + (struct hbm_client_connect_request *)ishtp_msg; 735 + ishtp_hbm_fw_disconnect_req(dev, disconnect_req); 736 + break; 737 + 738 + case FW_STOP_REQ_CMD: 739 + dev->hbm_state = ISHTP_HBM_STOPPED; 740 + break; 741 + 742 + case DMA_BUFFER_ALLOC_RESPONSE: 743 + dev->ishtp_host_dma_enabled = 1; 744 + break; 745 + 746 + case DMA_XFER: 747 + dma_xfer = (struct dma_xfer_hbm *)ishtp_msg; 748 + if (!dev->ishtp_host_dma_enabled) { 749 + dev_err(dev->devc, 750 + "DMA XFER requested but DMA is not enabled\n"); 751 + break; 752 + } 753 + ishtp_hbm_dma_xfer(dev, dma_xfer); 754 + break; 755 + 756 + case DMA_XFER_ACK: 757 + dma_xfer = (struct dma_xfer_hbm *)ishtp_msg; 758 + if (!dev->ishtp_host_dma_enabled || 759 + !dev->ishtp_host_dma_tx_buf) { 760 + dev_err(dev->devc, 761 + "DMA XFER acked but DMA Tx is not enabled\n"); 762 + break; 763 + } 764 + ishtp_hbm_dma_xfer_ack(dev, dma_xfer); 765 + break; 766 + 767 + default: 768 + dev_err(dev->devc, "unknown HBM: %u\n", 769 + (unsigned int)ishtp_msg->hbm_cmd); 770 + 771 + break; 772 + } 773 + } 774 + 775 + /** 776 + * bh_hbm_work_fn() - HBM work function 777 + * @work: work struct 778 + * 779 + * Bottom half processing work function (instead of thread handler) 780 + * for processing hbm messages 781 + */ 782 + void bh_hbm_work_fn(struct work_struct *work) 783 + { 784 + unsigned long flags; 785 + struct ishtp_device *dev; 786 + unsigned char hbm[IPC_PAYLOAD_SIZE]; 787 + 788 + dev = container_of(work, struct ishtp_device, bh_hbm_work); 789 + spin_lock_irqsave(&dev->rd_msg_spinlock, flags); 790 + if (dev->rd_msg_fifo_head != dev->rd_msg_fifo_tail) { 791 + memcpy(hbm, dev->rd_msg_fifo + dev->rd_msg_fifo_head, 792 + IPC_PAYLOAD_SIZE); 793 + dev->rd_msg_fifo_head = 794 + (dev->rd_msg_fifo_head + IPC_PAYLOAD_SIZE) % 795 + (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE); 796 + spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags); 797 + ishtp_hbm_dispatch(dev, (struct ishtp_bus_message *)hbm); 798 + } else { 799 + spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags); 800 + } 801 + } 802 + 803 + /** 804 + * recv_hbm() - Receive HBM message 805 + * @dev: ISHTP device instance 806 + * @ishtp_hdr: received bus message 807 + * 808 + * Receive and process ISHTP bus messages in ISR context. This will schedule 809 + * work function to process message 810 + */ 811 + void recv_hbm(struct ishtp_device *dev, struct ishtp_msg_hdr *ishtp_hdr) 812 + { 813 + uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE]; 814 + struct ishtp_bus_message *ishtp_msg = 815 + (struct ishtp_bus_message *)rd_msg_buf; 816 + unsigned long flags; 817 + 818 + dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length); 819 + 820 + /* Flow control - handle in place */ 821 + if (ishtp_msg->hbm_cmd == ISHTP_FLOW_CONTROL_CMD) { 822 + struct hbm_flow_control *flow_control = 823 + (struct hbm_flow_control *)ishtp_msg; 824 + struct ishtp_cl *cl = NULL; 825 + unsigned long flags, tx_flags; 826 + 827 + spin_lock_irqsave(&dev->cl_list_lock, flags); 828 + list_for_each_entry(cl, &dev->cl_list, link) { 829 + if (cl->host_client_id == flow_control->host_addr && 830 + cl->fw_client_id == 831 + flow_control->fw_addr) { 832 + /* 833 + * NOTE: It's valid only for counting 834 + * flow-control implementation to receive a 835 + * FC in the middle of sending. Meanwhile not 836 + * supported 837 + */ 838 + if (cl->ishtp_flow_ctrl_creds) 839 + dev_err(dev->devc, 840 + "recv extra FC from FW client %u (host client %u) (FC count was %d)\n", 841 + (unsigned int)cl->fw_client_id, 842 + (unsigned int)cl->host_client_id, 843 + cl->ishtp_flow_ctrl_creds); 844 + else { 845 + ++cl->ishtp_flow_ctrl_creds; 846 + ++cl->ishtp_flow_ctrl_cnt; 847 + cl->last_ipc_acked = 1; 848 + spin_lock_irqsave( 849 + &cl->tx_list_spinlock, 850 + tx_flags); 851 + if (!list_empty(&cl->tx_list.list)) { 852 + /* 853 + * start sending the first msg 854 + * = the callback function 855 + */ 856 + spin_unlock_irqrestore( 857 + &cl->tx_list_spinlock, 858 + tx_flags); 859 + ishtp_cl_send_msg(dev, cl); 860 + } else { 861 + spin_unlock_irqrestore( 862 + &cl->tx_list_spinlock, 863 + tx_flags); 864 + } 865 + } 866 + break; 867 + } 868 + } 869 + spin_unlock_irqrestore(&dev->cl_list_lock, flags); 870 + goto eoi; 871 + } 872 + 873 + /* 874 + * Some messages that are safe for ISR processing and important 875 + * to be done "quickly" and in-order, go here 876 + */ 877 + if (ishtp_msg->hbm_cmd == CLIENT_CONNECT_RES_CMD || 878 + ishtp_msg->hbm_cmd == CLIENT_DISCONNECT_RES_CMD || 879 + ishtp_msg->hbm_cmd == CLIENT_DISCONNECT_REQ_CMD || 880 + ishtp_msg->hbm_cmd == DMA_XFER) { 881 + ishtp_hbm_dispatch(dev, ishtp_msg); 882 + goto eoi; 883 + } 884 + 885 + /* 886 + * All other HBMs go here. 887 + * We schedule HBMs for processing serially by using system wq, 888 + * possibly there will be multiple HBMs scheduled at the same time. 889 + */ 890 + spin_lock_irqsave(&dev->rd_msg_spinlock, flags); 891 + if ((dev->rd_msg_fifo_tail + IPC_PAYLOAD_SIZE) % 892 + (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE) == 893 + dev->rd_msg_fifo_head) { 894 + spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags); 895 + dev_err(dev->devc, "BH buffer overflow, dropping HBM %u\n", 896 + (unsigned int)ishtp_msg->hbm_cmd); 897 + goto eoi; 898 + } 899 + memcpy(dev->rd_msg_fifo + dev->rd_msg_fifo_tail, ishtp_msg, 900 + ishtp_hdr->length); 901 + dev->rd_msg_fifo_tail = (dev->rd_msg_fifo_tail + IPC_PAYLOAD_SIZE) % 902 + (RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE); 903 + spin_unlock_irqrestore(&dev->rd_msg_spinlock, flags); 904 + schedule_work(&dev->bh_hbm_work); 905 + eoi: 906 + return; 907 + } 908 + 909 + /** 910 + * recv_fixed_cl_msg() - Receive fixed client message 911 + * @dev: ISHTP device instance 912 + * @ishtp_hdr: received bus message 913 + * 914 + * Receive and process ISHTP fixed client messages (address == 0) 915 + * in ISR context 916 + */ 917 + void recv_fixed_cl_msg(struct ishtp_device *dev, 918 + struct ishtp_msg_hdr *ishtp_hdr) 919 + { 920 + uint8_t rd_msg_buf[ISHTP_RD_MSG_BUF_SIZE]; 921 + 922 + dev->print_log(dev, 923 + "%s() got fixed client msg from client #%d\n", 924 + __func__, ishtp_hdr->fw_addr); 925 + dev->ops->ishtp_read(dev, rd_msg_buf, ishtp_hdr->length); 926 + if (ishtp_hdr->fw_addr == ISHTP_SYSTEM_STATE_CLIENT_ADDR) { 927 + struct ish_system_states_header *msg_hdr = 928 + (struct ish_system_states_header *)rd_msg_buf; 929 + if (msg_hdr->cmd == SYSTEM_STATE_SUBSCRIBE) 930 + ishtp_send_resume(dev); 931 + /* if FW request arrived here, the system is not suspended */ 932 + else 933 + dev_err(dev->devc, "unknown fixed client msg [%02X]\n", 934 + msg_hdr->cmd); 935 + } 936 + } 937 + 938 + /** 939 + * fix_cl_hdr() - Initialize fixed client header 940 + * @hdr: message header 941 + * @length: length of message 942 + * @cl_addr: Client address 943 + * 944 + * Initialize message header for fixed client 945 + */ 946 + static inline void fix_cl_hdr(struct ishtp_msg_hdr *hdr, size_t length, 947 + uint8_t cl_addr) 948 + { 949 + hdr->host_addr = 0; 950 + hdr->fw_addr = cl_addr; 951 + hdr->length = length; 952 + hdr->msg_complete = 1; 953 + hdr->reserved = 0; 954 + } 955 + 956 + /*** Suspend and resume notification ***/ 957 + 958 + static uint32_t current_state; 959 + static uint32_t supported_states = 0 | SUSPEND_STATE_BIT; 960 + 961 + /** 962 + * ishtp_send_suspend() - Send suspend message to FW 963 + * @dev: ISHTP device instance 964 + * 965 + * Send suspend message to FW. This is useful for system freeze (non S3) case 966 + */ 967 + void ishtp_send_suspend(struct ishtp_device *dev) 968 + { 969 + struct ishtp_msg_hdr ishtp_hdr; 970 + struct ish_system_states_status state_status_msg; 971 + const size_t len = sizeof(struct ish_system_states_status); 972 + 973 + fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR); 974 + 975 + memset(&state_status_msg, 0, len); 976 + state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS; 977 + state_status_msg.supported_states = supported_states; 978 + current_state |= SUSPEND_STATE_BIT; 979 + dev->print_log(dev, "%s() sends SUSPEND notification\n", __func__); 980 + state_status_msg.states_status = current_state; 981 + 982 + ishtp_write_message(dev, &ishtp_hdr, 983 + (unsigned char *)&state_status_msg); 984 + } 985 + EXPORT_SYMBOL(ishtp_send_suspend); 986 + 987 + /** 988 + * ishtp_send_resume() - Send resume message to FW 989 + * @dev: ISHTP device instance 990 + * 991 + * Send resume message to FW. This is useful for system freeze (non S3) case 992 + */ 993 + void ishtp_send_resume(struct ishtp_device *dev) 994 + { 995 + struct ishtp_msg_hdr ishtp_hdr; 996 + struct ish_system_states_status state_status_msg; 997 + const size_t len = sizeof(struct ish_system_states_status); 998 + 999 + fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR); 1000 + 1001 + memset(&state_status_msg, 0, len); 1002 + state_status_msg.hdr.cmd = SYSTEM_STATE_STATUS; 1003 + state_status_msg.supported_states = supported_states; 1004 + current_state &= ~SUSPEND_STATE_BIT; 1005 + dev->print_log(dev, "%s() sends RESUME notification\n", __func__); 1006 + state_status_msg.states_status = current_state; 1007 + 1008 + ishtp_write_message(dev, &ishtp_hdr, 1009 + (unsigned char *)&state_status_msg); 1010 + } 1011 + EXPORT_SYMBOL(ishtp_send_resume); 1012 + 1013 + /** 1014 + * ishtp_query_subscribers() - Send query subscribers message 1015 + * @dev: ISHTP device instance 1016 + * 1017 + * Send message to query subscribers 1018 + */ 1019 + void ishtp_query_subscribers(struct ishtp_device *dev) 1020 + { 1021 + struct ishtp_msg_hdr ishtp_hdr; 1022 + struct ish_system_states_query_subscribers query_subscribers_msg; 1023 + const size_t len = sizeof(struct ish_system_states_query_subscribers); 1024 + 1025 + fix_cl_hdr(&ishtp_hdr, len, ISHTP_SYSTEM_STATE_CLIENT_ADDR); 1026 + 1027 + memset(&query_subscribers_msg, 0, len); 1028 + query_subscribers_msg.hdr.cmd = SYSTEM_STATE_QUERY_SUBSCRIBERS; 1029 + 1030 + ishtp_write_message(dev, &ishtp_hdr, 1031 + (unsigned char *)&query_subscribers_msg); 1032 + }
+321
drivers/hid/intel-ish-hid/ishtp/hbm.h
··· 1 + /* 2 + * ISHTP bus layer messages handling 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #ifndef _ISHTP_HBM_H_ 17 + #define _ISHTP_HBM_H_ 18 + 19 + #include <linux/uuid.h> 20 + 21 + struct ishtp_device; 22 + struct ishtp_msg_hdr; 23 + struct ishtp_cl; 24 + 25 + /* 26 + * Timeouts in Seconds 27 + */ 28 + #define ISHTP_INTEROP_TIMEOUT 7 /* Timeout on ready message */ 29 + 30 + #define ISHTP_CL_CONNECT_TIMEOUT 15 /* HPS: Client Connect Timeout */ 31 + 32 + /* 33 + * ISHTP Version 34 + */ 35 + #define HBM_MINOR_VERSION 0 36 + #define HBM_MAJOR_VERSION 1 37 + 38 + /* Host bus message command opcode */ 39 + #define ISHTP_HBM_CMD_OP_MSK 0x7f 40 + /* Host bus message command RESPONSE */ 41 + #define ISHTP_HBM_CMD_RES_MSK 0x80 42 + 43 + /* 44 + * ISHTP Bus Message Command IDs 45 + */ 46 + #define HOST_START_REQ_CMD 0x01 47 + #define HOST_START_RES_CMD 0x81 48 + 49 + #define HOST_STOP_REQ_CMD 0x02 50 + #define HOST_STOP_RES_CMD 0x82 51 + 52 + #define FW_STOP_REQ_CMD 0x03 53 + 54 + #define HOST_ENUM_REQ_CMD 0x04 55 + #define HOST_ENUM_RES_CMD 0x84 56 + 57 + #define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05 58 + #define HOST_CLIENT_PROPERTIES_RES_CMD 0x85 59 + 60 + #define CLIENT_CONNECT_REQ_CMD 0x06 61 + #define CLIENT_CONNECT_RES_CMD 0x86 62 + 63 + #define CLIENT_DISCONNECT_REQ_CMD 0x07 64 + #define CLIENT_DISCONNECT_RES_CMD 0x87 65 + 66 + #define ISHTP_FLOW_CONTROL_CMD 0x08 67 + 68 + #define DMA_BUFFER_ALLOC_NOTIFY 0x11 69 + #define DMA_BUFFER_ALLOC_RESPONSE 0x91 70 + 71 + #define DMA_XFER 0x12 72 + #define DMA_XFER_ACK 0x92 73 + 74 + /* 75 + * ISHTP Stop Reason 76 + * used by hbm_host_stop_request.reason 77 + */ 78 + #define DRIVER_STOP_REQUEST 0x00 79 + 80 + /* 81 + * ISHTP BUS Interface Section 82 + */ 83 + struct ishtp_msg_hdr { 84 + uint32_t fw_addr:8; 85 + uint32_t host_addr:8; 86 + uint32_t length:9; 87 + uint32_t reserved:6; 88 + uint32_t msg_complete:1; 89 + } __packed; 90 + 91 + struct ishtp_bus_message { 92 + uint8_t hbm_cmd; 93 + uint8_t data[0]; 94 + } __packed; 95 + 96 + /** 97 + * struct hbm_cl_cmd - client specific host bus command 98 + * CONNECT, DISCONNECT, and FlOW CONTROL 99 + * 100 + * @hbm_cmd - bus message command header 101 + * @fw_addr - address of the fw client 102 + * @host_addr - address of the client in the driver 103 + * @data 104 + */ 105 + struct ishtp_hbm_cl_cmd { 106 + uint8_t hbm_cmd; 107 + uint8_t fw_addr; 108 + uint8_t host_addr; 109 + uint8_t data; 110 + }; 111 + 112 + struct hbm_version { 113 + uint8_t minor_version; 114 + uint8_t major_version; 115 + } __packed; 116 + 117 + struct hbm_host_version_request { 118 + uint8_t hbm_cmd; 119 + uint8_t reserved; 120 + struct hbm_version host_version; 121 + } __packed; 122 + 123 + struct hbm_host_version_response { 124 + uint8_t hbm_cmd; 125 + uint8_t host_version_supported; 126 + struct hbm_version fw_max_version; 127 + } __packed; 128 + 129 + struct hbm_host_stop_request { 130 + uint8_t hbm_cmd; 131 + uint8_t reason; 132 + uint8_t reserved[2]; 133 + } __packed; 134 + 135 + struct hbm_host_stop_response { 136 + uint8_t hbm_cmd; 137 + uint8_t reserved[3]; 138 + } __packed; 139 + 140 + struct hbm_host_enum_request { 141 + uint8_t hbm_cmd; 142 + uint8_t reserved[3]; 143 + } __packed; 144 + 145 + struct hbm_host_enum_response { 146 + uint8_t hbm_cmd; 147 + uint8_t reserved[3]; 148 + uint8_t valid_addresses[32]; 149 + } __packed; 150 + 151 + struct ishtp_client_properties { 152 + uuid_le protocol_name; 153 + uint8_t protocol_version; 154 + uint8_t max_number_of_connections; 155 + uint8_t fixed_address; 156 + uint8_t single_recv_buf; 157 + uint32_t max_msg_length; 158 + uint8_t dma_hdr_len; 159 + #define ISHTP_CLIENT_DMA_ENABLED 0x80 160 + uint8_t reserved4; 161 + uint8_t reserved5; 162 + uint8_t reserved6; 163 + } __packed; 164 + 165 + struct hbm_props_request { 166 + uint8_t hbm_cmd; 167 + uint8_t address; 168 + uint8_t reserved[2]; 169 + } __packed; 170 + 171 + struct hbm_props_response { 172 + uint8_t hbm_cmd; 173 + uint8_t address; 174 + uint8_t status; 175 + uint8_t reserved[1]; 176 + struct ishtp_client_properties client_properties; 177 + } __packed; 178 + 179 + /** 180 + * struct hbm_client_connect_request - connect/disconnect request 181 + * 182 + * @hbm_cmd - bus message command header 183 + * @fw_addr - address of the fw client 184 + * @host_addr - address of the client in the driver 185 + * @reserved 186 + */ 187 + struct hbm_client_connect_request { 188 + uint8_t hbm_cmd; 189 + uint8_t fw_addr; 190 + uint8_t host_addr; 191 + uint8_t reserved; 192 + } __packed; 193 + 194 + /** 195 + * struct hbm_client_connect_response - connect/disconnect response 196 + * 197 + * @hbm_cmd - bus message command header 198 + * @fw_addr - address of the fw client 199 + * @host_addr - address of the client in the driver 200 + * @status - status of the request 201 + */ 202 + struct hbm_client_connect_response { 203 + uint8_t hbm_cmd; 204 + uint8_t fw_addr; 205 + uint8_t host_addr; 206 + uint8_t status; 207 + } __packed; 208 + 209 + 210 + #define ISHTP_FC_MESSAGE_RESERVED_LENGTH 5 211 + 212 + struct hbm_flow_control { 213 + uint8_t hbm_cmd; 214 + uint8_t fw_addr; 215 + uint8_t host_addr; 216 + uint8_t reserved[ISHTP_FC_MESSAGE_RESERVED_LENGTH]; 217 + } __packed; 218 + 219 + struct dma_alloc_notify { 220 + uint8_t hbm; 221 + uint8_t status; 222 + uint8_t reserved[2]; 223 + uint32_t buf_size; 224 + uint64_t buf_address; 225 + /* [...] May come more size/address pairs */ 226 + } __packed; 227 + 228 + struct dma_xfer_hbm { 229 + uint8_t hbm; 230 + uint8_t fw_client_id; 231 + uint8_t host_client_id; 232 + uint8_t reserved; 233 + uint64_t msg_addr; 234 + uint32_t msg_length; 235 + uint32_t reserved2; 236 + } __packed; 237 + 238 + /* System state */ 239 + #define ISHTP_SYSTEM_STATE_CLIENT_ADDR 13 240 + 241 + #define SYSTEM_STATE_SUBSCRIBE 0x1 242 + #define SYSTEM_STATE_STATUS 0x2 243 + #define SYSTEM_STATE_QUERY_SUBSCRIBERS 0x3 244 + #define SYSTEM_STATE_STATE_CHANGE_REQ 0x4 245 + /*indicates suspend and resume states*/ 246 + #define SUSPEND_STATE_BIT (1<<1) 247 + 248 + struct ish_system_states_header { 249 + uint32_t cmd; 250 + uint32_t cmd_status; /*responses will have this set*/ 251 + } __packed; 252 + 253 + struct ish_system_states_subscribe { 254 + struct ish_system_states_header hdr; 255 + uint32_t states; 256 + } __packed; 257 + 258 + struct ish_system_states_status { 259 + struct ish_system_states_header hdr; 260 + uint32_t supported_states; 261 + uint32_t states_status; 262 + } __packed; 263 + 264 + struct ish_system_states_query_subscribers { 265 + struct ish_system_states_header hdr; 266 + } __packed; 267 + 268 + struct ish_system_states_state_change_req { 269 + struct ish_system_states_header hdr; 270 + uint32_t requested_states; 271 + uint32_t states_status; 272 + } __packed; 273 + 274 + /** 275 + * enum ishtp_hbm_state - host bus message protocol state 276 + * 277 + * @ISHTP_HBM_IDLE : protocol not started 278 + * @ISHTP_HBM_START : start request message was sent 279 + * @ISHTP_HBM_ENUM_CLIENTS : enumeration request was sent 280 + * @ISHTP_HBM_CLIENT_PROPERTIES : acquiring clients properties 281 + */ 282 + enum ishtp_hbm_state { 283 + ISHTP_HBM_IDLE = 0, 284 + ISHTP_HBM_START, 285 + ISHTP_HBM_STARTED, 286 + ISHTP_HBM_ENUM_CLIENTS, 287 + ISHTP_HBM_CLIENT_PROPERTIES, 288 + ISHTP_HBM_WORKING, 289 + ISHTP_HBM_STOPPED, 290 + }; 291 + 292 + static inline void ishtp_hbm_hdr(struct ishtp_msg_hdr *hdr, size_t length) 293 + { 294 + hdr->host_addr = 0; 295 + hdr->fw_addr = 0; 296 + hdr->length = length; 297 + hdr->msg_complete = 1; 298 + hdr->reserved = 0; 299 + } 300 + 301 + int ishtp_hbm_start_req(struct ishtp_device *dev); 302 + int ishtp_hbm_start_wait(struct ishtp_device *dev); 303 + int ishtp_hbm_cl_flow_control_req(struct ishtp_device *dev, 304 + struct ishtp_cl *cl); 305 + int ishtp_hbm_cl_disconnect_req(struct ishtp_device *dev, struct ishtp_cl *cl); 306 + int ishtp_hbm_cl_connect_req(struct ishtp_device *dev, struct ishtp_cl *cl); 307 + void ishtp_hbm_enum_clients_req(struct ishtp_device *dev); 308 + void bh_hbm_work_fn(struct work_struct *work); 309 + void recv_hbm(struct ishtp_device *dev, struct ishtp_msg_hdr *ishtp_hdr); 310 + void recv_fixed_cl_msg(struct ishtp_device *dev, 311 + struct ishtp_msg_hdr *ishtp_hdr); 312 + void ishtp_hbm_dispatch(struct ishtp_device *dev, 313 + struct ishtp_bus_message *hdr); 314 + 315 + void ishtp_query_subscribers(struct ishtp_device *dev); 316 + 317 + /* Exported I/F */ 318 + void ishtp_send_suspend(struct ishtp_device *dev); 319 + void ishtp_send_resume(struct ishtp_device *dev); 320 + 321 + #endif /* _ISHTP_HBM_H_ */
+115
drivers/hid/intel-ish-hid/ishtp/init.c
··· 1 + /* 2 + * Initialization protocol for ISHTP driver 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #include <linux/export.h> 17 + #include <linux/slab.h> 18 + #include <linux/sched.h> 19 + #include <linux/miscdevice.h> 20 + #include "ishtp-dev.h" 21 + #include "hbm.h" 22 + #include "client.h" 23 + 24 + /** 25 + * ishtp_dev_state_str() -Convert to string format 26 + * @state: state to convert 27 + * 28 + * Convert state to string for prints 29 + * 30 + * Return: character pointer to converted string 31 + */ 32 + const char *ishtp_dev_state_str(int state) 33 + { 34 + switch (state) { 35 + case ISHTP_DEV_INITIALIZING: 36 + return "INITIALIZING"; 37 + case ISHTP_DEV_INIT_CLIENTS: 38 + return "INIT_CLIENTS"; 39 + case ISHTP_DEV_ENABLED: 40 + return "ENABLED"; 41 + case ISHTP_DEV_RESETTING: 42 + return "RESETTING"; 43 + case ISHTP_DEV_DISABLED: 44 + return "DISABLED"; 45 + case ISHTP_DEV_POWER_DOWN: 46 + return "POWER_DOWN"; 47 + case ISHTP_DEV_POWER_UP: 48 + return "POWER_UP"; 49 + default: 50 + return "unknown"; 51 + } 52 + } 53 + 54 + /** 55 + * ishtp_device_init() - ishtp device init 56 + * @dev: ISHTP device instance 57 + * 58 + * After ISHTP device is alloacted, this function is used to initialize 59 + * each field which includes spin lock, work struct and lists 60 + */ 61 + void ishtp_device_init(struct ishtp_device *dev) 62 + { 63 + dev->dev_state = ISHTP_DEV_INITIALIZING; 64 + INIT_LIST_HEAD(&dev->cl_list); 65 + INIT_LIST_HEAD(&dev->device_list); 66 + dev->rd_msg_fifo_head = 0; 67 + dev->rd_msg_fifo_tail = 0; 68 + spin_lock_init(&dev->rd_msg_spinlock); 69 + 70 + init_waitqueue_head(&dev->wait_hbm_recvd_msg); 71 + spin_lock_init(&dev->read_list_spinlock); 72 + spin_lock_init(&dev->device_lock); 73 + spin_lock_init(&dev->device_list_lock); 74 + spin_lock_init(&dev->cl_list_lock); 75 + spin_lock_init(&dev->fw_clients_lock); 76 + INIT_WORK(&dev->bh_hbm_work, bh_hbm_work_fn); 77 + 78 + bitmap_zero(dev->host_clients_map, ISHTP_CLIENTS_MAX); 79 + dev->open_handle_count = 0; 80 + 81 + /* 82 + * Reserving client ID 0 for ISHTP Bus Message communications 83 + */ 84 + bitmap_set(dev->host_clients_map, 0, 1); 85 + 86 + INIT_LIST_HEAD(&dev->read_list.list); 87 + 88 + } 89 + EXPORT_SYMBOL(ishtp_device_init); 90 + 91 + /** 92 + * ishtp_start() - Start ISH processing 93 + * @dev: ISHTP device instance 94 + * 95 + * Start ISHTP processing by sending query subscriber message 96 + * 97 + * Return: 0 on success else -ENODEV 98 + */ 99 + int ishtp_start(struct ishtp_device *dev) 100 + { 101 + if (ishtp_hbm_start_wait(dev)) { 102 + dev_err(dev->devc, "HBM haven't started"); 103 + goto err; 104 + } 105 + 106 + /* suspend & resume notification - send QUERY_SUBSCRIBERS msg */ 107 + ishtp_query_subscribers(dev); 108 + 109 + return 0; 110 + err: 111 + dev_err(dev->devc, "link layer initialization failed.\n"); 112 + dev->dev_state = ISHTP_DEV_DISABLED; 113 + return -ENODEV; 114 + } 115 + EXPORT_SYMBOL(ishtp_start);
+277
drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h
··· 1 + /* 2 + * Most ISHTP provider device and ISHTP logic declarations 3 + * 4 + * Copyright (c) 2003-2016, Intel Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms and conditions of the GNU General Public License, 8 + * version 2, as published by the Free Software Foundation. 9 + * 10 + * This program is distributed in the hope it will be useful, but WITHOUT 11 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 + * more details. 14 + */ 15 + 16 + #ifndef _ISHTP_DEV_H_ 17 + #define _ISHTP_DEV_H_ 18 + 19 + #include <linux/types.h> 20 + #include <linux/spinlock.h> 21 + #include "bus.h" 22 + #include "hbm.h" 23 + 24 + #define IPC_PAYLOAD_SIZE 128 25 + #define ISHTP_RD_MSG_BUF_SIZE IPC_PAYLOAD_SIZE 26 + #define IPC_FULL_MSG_SIZE 132 27 + 28 + /* Number of messages to be held in ISR->BH FIFO */ 29 + #define RD_INT_FIFO_SIZE 64 30 + 31 + /* 32 + * Number of IPC messages to be held in Tx FIFO, to be sent by ISR - 33 + * Tx complete interrupt or RX_COMPLETE handler 34 + */ 35 + #define IPC_TX_FIFO_SIZE 512 36 + 37 + /* 38 + * Number of Maximum ISHTP Clients 39 + */ 40 + #define ISHTP_CLIENTS_MAX 256 41 + 42 + /* 43 + * Number of File descriptors/handles 44 + * that can be opened to the driver. 45 + * 46 + * Limit to 255: 256 Total Clients 47 + * minus internal client for ISHTP Bus Messages 48 + */ 49 + #define ISHTP_MAX_OPEN_HANDLE_COUNT (ISHTP_CLIENTS_MAX - 1) 50 + 51 + /* Internal Clients Number */ 52 + #define ISHTP_HOST_CLIENT_ID_ANY (-1) 53 + #define ISHTP_HBM_HOST_CLIENT_ID 0 54 + 55 + #define MAX_DMA_DELAY 20 56 + 57 + /* ISHTP device states */ 58 + enum ishtp_dev_state { 59 + ISHTP_DEV_INITIALIZING = 0, 60 + ISHTP_DEV_INIT_CLIENTS, 61 + ISHTP_DEV_ENABLED, 62 + ISHTP_DEV_RESETTING, 63 + ISHTP_DEV_DISABLED, 64 + ISHTP_DEV_POWER_DOWN, 65 + ISHTP_DEV_POWER_UP 66 + }; 67 + const char *ishtp_dev_state_str(int state); 68 + 69 + struct ishtp_cl; 70 + 71 + /** 72 + * struct ishtp_fw_client - representation of fw client 73 + * 74 + * @props - client properties 75 + * @client_id - fw client id 76 + */ 77 + struct ishtp_fw_client { 78 + struct ishtp_client_properties props; 79 + uint8_t client_id; 80 + }; 81 + 82 + /** 83 + * struct ishtp_msg_data - ISHTP message data struct 84 + * @size: Size of data in the *data 85 + * @data: Pointer to data 86 + */ 87 + struct ishtp_msg_data { 88 + uint32_t size; 89 + unsigned char *data; 90 + }; 91 + 92 + /* 93 + * struct ishtp_cl_rb - request block structure 94 + * @list: Link to list members 95 + * @cl: ISHTP client instance 96 + * @buffer: message header 97 + * @buf_idx: Index into buffer 98 + * @read_time: unused at this time 99 + */ 100 + struct ishtp_cl_rb { 101 + struct list_head list; 102 + struct ishtp_cl *cl; 103 + struct ishtp_msg_data buffer; 104 + unsigned long buf_idx; 105 + unsigned long read_time; 106 + }; 107 + 108 + /* 109 + * Control info for IPC messages ISHTP/IPC sending FIFO - 110 + * list with inline data buffer 111 + * This structure will be filled with parameters submitted 112 + * by the caller glue layer 113 + * 'buf' may be pointing to the external buffer or to 'inline_data' 114 + * 'offset' will be initialized to 0 by submitting 115 + * 116 + * 'ipc_send_compl' is intended for use by clients that send fragmented 117 + * messages. When a fragment is sent down to IPC msg regs, 118 + * it will be called. 119 + * If it has more fragments to send, it will do it. With last fragment 120 + * it will send appropriate ISHTP "message-complete" flag. 121 + * It will remove the outstanding message 122 + * (mark outstanding buffer as available). 123 + * If counting flow control is in work and there are more flow control 124 + * credits, it can put the next client message queued in cl. 125 + * structure for IPC processing. 126 + * 127 + */ 128 + struct wr_msg_ctl_info { 129 + /* Will be called with 'ipc_send_compl_prm' as parameter */ 130 + void (*ipc_send_compl)(void *); 131 + 132 + void *ipc_send_compl_prm; 133 + size_t length; 134 + struct list_head link; 135 + unsigned char inline_data[IPC_FULL_MSG_SIZE]; 136 + }; 137 + 138 + /* 139 + * The ISHTP layer talks to hardware IPC message using the following 140 + * callbacks 141 + */ 142 + struct ishtp_hw_ops { 143 + int (*hw_reset)(struct ishtp_device *dev); 144 + int (*ipc_reset)(struct ishtp_device *dev); 145 + uint32_t (*ipc_get_header)(struct ishtp_device *dev, int length, 146 + int busy); 147 + int (*write)(struct ishtp_device *dev, 148 + void (*ipc_send_compl)(void *), void *ipc_send_compl_prm, 149 + unsigned char *msg, int length); 150 + uint32_t (*ishtp_read_hdr)(const struct ishtp_device *dev); 151 + int (*ishtp_read)(struct ishtp_device *dev, unsigned char *buffer, 152 + unsigned long buffer_length); 153 + uint32_t (*get_fw_status)(struct ishtp_device *dev); 154 + void (*sync_fw_clock)(struct ishtp_device *dev); 155 + }; 156 + 157 + /** 158 + * struct ishtp_device - ISHTP private device struct 159 + */ 160 + struct ishtp_device { 161 + struct device *devc; /* pointer to lowest device */ 162 + struct pci_dev *pdev; /* PCI device to get device ids */ 163 + 164 + /* waitq for waiting for suspend response */ 165 + wait_queue_head_t suspend_wait; 166 + bool suspend_flag; /* Suspend is active */ 167 + 168 + /* waitq for waiting for resume response */ 169 + wait_queue_head_t resume_wait; 170 + bool resume_flag; /*Resume is active */ 171 + 172 + /* 173 + * lock for the device, for everything that doesn't have 174 + * a dedicated spinlock 175 + */ 176 + spinlock_t device_lock; 177 + 178 + bool recvd_hw_ready; 179 + struct hbm_version version; 180 + int transfer_path; /* Choice of transfer path: IPC or DMA */ 181 + 182 + /* ishtp device states */ 183 + enum ishtp_dev_state dev_state; 184 + enum ishtp_hbm_state hbm_state; 185 + 186 + /* driver read queue */ 187 + struct ishtp_cl_rb read_list; 188 + spinlock_t read_list_spinlock; 189 + 190 + /* list of ishtp_cl's */ 191 + struct list_head cl_list; 192 + spinlock_t cl_list_lock; 193 + long open_handle_count; 194 + 195 + /* List of bus devices */ 196 + struct list_head device_list; 197 + spinlock_t device_list_lock; 198 + 199 + /* waiting queues for receive message from FW */ 200 + wait_queue_head_t wait_hw_ready; 201 + wait_queue_head_t wait_hbm_recvd_msg; 202 + 203 + /* FIFO for input messages for BH processing */ 204 + unsigned char rd_msg_fifo[RD_INT_FIFO_SIZE * IPC_PAYLOAD_SIZE]; 205 + unsigned int rd_msg_fifo_head, rd_msg_fifo_tail; 206 + spinlock_t rd_msg_spinlock; 207 + struct work_struct bh_hbm_work; 208 + 209 + /* IPC write queue */ 210 + struct wr_msg_ctl_info wr_processing_list_head, wr_free_list_head; 211 + /* For both processing list and free list */ 212 + spinlock_t wr_processing_spinlock; 213 + 214 + spinlock_t out_ipc_spinlock; 215 + 216 + struct ishtp_fw_client *fw_clients; /*Note:memory has to be allocated*/ 217 + DECLARE_BITMAP(fw_clients_map, ISHTP_CLIENTS_MAX); 218 + DECLARE_BITMAP(host_clients_map, ISHTP_CLIENTS_MAX); 219 + uint8_t fw_clients_num; 220 + uint8_t fw_client_presentation_num; 221 + uint8_t fw_client_index; 222 + spinlock_t fw_clients_lock; 223 + 224 + /* TX DMA buffers and slots */ 225 + int ishtp_host_dma_enabled; 226 + void *ishtp_host_dma_tx_buf; 227 + unsigned int ishtp_host_dma_tx_buf_size; 228 + uint64_t ishtp_host_dma_tx_buf_phys; 229 + int ishtp_dma_num_slots; 230 + 231 + /* map of 4k blocks in Tx dma buf: 0-free, 1-used */ 232 + uint8_t *ishtp_dma_tx_map; 233 + spinlock_t ishtp_dma_tx_lock; 234 + 235 + /* RX DMA buffers and slots */ 236 + void *ishtp_host_dma_rx_buf; 237 + unsigned int ishtp_host_dma_rx_buf_size; 238 + uint64_t ishtp_host_dma_rx_buf_phys; 239 + 240 + /* Dump to trace buffers if enabled*/ 241 + void (*print_log)(struct ishtp_device *dev, char *format, ...); 242 + 243 + /* Debug stats */ 244 + unsigned int ipc_rx_cnt; 245 + unsigned long long ipc_rx_bytes_cnt; 246 + unsigned int ipc_tx_cnt; 247 + unsigned long long ipc_tx_bytes_cnt; 248 + 249 + const struct ishtp_hw_ops *ops; 250 + size_t mtu; 251 + uint32_t ishtp_msg_hdr; 252 + char hw[0] __aligned(sizeof(void *)); 253 + }; 254 + 255 + static inline unsigned long ishtp_secs_to_jiffies(unsigned long sec) 256 + { 257 + return msecs_to_jiffies(sec * MSEC_PER_SEC); 258 + } 259 + 260 + /* 261 + * Register Access Function 262 + */ 263 + static inline int ish_ipc_reset(struct ishtp_device *dev) 264 + { 265 + return dev->ops->ipc_reset(dev); 266 + } 267 + 268 + static inline int ish_hw_reset(struct ishtp_device *dev) 269 + { 270 + return dev->ops->hw_reset(dev); 271 + } 272 + 273 + /* Exported function */ 274 + void ishtp_device_init(struct ishtp_device *dev); 275 + int ishtp_start(struct ishtp_device *dev); 276 + 277 + #endif /*_ISHTP_DEV_H_*/
+3 -1
drivers/hid/usbhid/hid-quirks.c
··· 76 76 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K95RGB, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, 77 77 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K70RGB, HID_QUIRK_NO_INIT_REPORTS }, 78 78 { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_K65RGB, HID_QUIRK_NO_INIT_REPORTS }, 79 + { USB_VENDOR_ID_CORSAIR, USB_DEVICE_ID_CORSAIR_STRAFE, HID_QUIRK_NO_INIT_REPORTS | HID_QUIRK_ALWAYS_POLL }, 79 80 { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET }, 80 81 { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, 81 82 { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT }, ··· 99 98 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3, HID_QUIRK_NO_INIT_REPORTS }, 100 99 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_2, HID_QUIRK_NO_INIT_REPORTS }, 101 100 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_3_JP, HID_QUIRK_NO_INIT_REPORTS }, 101 + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_PRO_4_JP, HID_QUIRK_NO_INIT_REPORTS }, 102 102 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, 103 103 { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, 104 104 { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, ··· 145 143 { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS, HID_QUIRK_MULTI_INPUT }, 146 144 { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, 147 145 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, 148 - { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_2, HID_QUIRK_MULTI_INPUT }, 146 + { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X_V2, HID_QUIRK_MULTI_INPUT }, 149 147 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, 150 148 { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_PENSKETCH_M912, HID_QUIRK_MULTI_INPUT }, 151 149 { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS },
+81 -15
drivers/hid/wacom.h
··· 90 90 #include <linux/module.h> 91 91 #include <linux/mod_devicetable.h> 92 92 #include <linux/hid.h> 93 + #include <linux/kfifo.h> 94 + #include <linux/leds.h> 93 95 #include <linux/usb/input.h> 94 96 #include <linux/power_supply.h> 95 97 #include <asm/unaligned.h> ··· 107 105 #define USB_VENDOR_ID_WACOM 0x056a 108 106 #define USB_VENDOR_ID_LENOVO 0x17ef 109 107 108 + enum wacom_worker { 109 + WACOM_WORKER_WIRELESS, 110 + WACOM_WORKER_BATTERY, 111 + WACOM_WORKER_REMOTE, 112 + }; 113 + 114 + struct wacom; 115 + 116 + struct wacom_led { 117 + struct led_classdev cdev; 118 + struct led_trigger trigger; 119 + struct wacom *wacom; 120 + unsigned int group; 121 + unsigned int id; 122 + u8 llv; 123 + u8 hlv; 124 + bool held; 125 + }; 126 + 127 + struct wacom_group_leds { 128 + u8 select; /* status led selector (0..3) */ 129 + struct wacom_led *leds; 130 + unsigned int count; 131 + struct device *dev; 132 + }; 133 + 134 + struct wacom_battery { 135 + struct wacom *wacom; 136 + struct power_supply_desc bat_desc; 137 + struct power_supply *battery; 138 + char bat_name[WACOM_NAME_MAX]; 139 + int battery_capacity; 140 + int bat_charging; 141 + int bat_connected; 142 + int ps_connected; 143 + }; 144 + 145 + struct wacom_remote { 146 + spinlock_t remote_lock; 147 + struct kfifo remote_fifo; 148 + struct kobject *remote_dir; 149 + struct { 150 + struct attribute_group group; 151 + u32 serial; 152 + struct input_dev *input; 153 + bool registered; 154 + struct wacom_battery battery; 155 + } remotes[WACOM_MAX_REMOTES]; 156 + }; 157 + 110 158 struct wacom { 111 159 struct usb_device *usbdev; 112 160 struct usb_interface *intf; 113 161 struct wacom_wac wacom_wac; 114 162 struct hid_device *hdev; 115 163 struct mutex lock; 116 - struct work_struct work; 117 - struct wacom_led { 118 - u8 select[5]; /* status led selector (0..3) */ 164 + struct work_struct wireless_work; 165 + struct work_struct battery_work; 166 + struct work_struct remote_work; 167 + struct wacom_remote *remote; 168 + struct wacom_leds { 169 + struct wacom_group_leds *groups; 170 + unsigned int count; 119 171 u8 llv; /* status led brightness no button (1..127) */ 120 172 u8 hlv; /* status led brightness button pressed (1..127) */ 121 173 u8 img_lum; /* OLED matrix display brightness */ 174 + u8 max_llv; /* maximum brightness of LED (llv) */ 175 + u8 max_hlv; /* maximum brightness of LED (hlv) */ 122 176 } led; 123 - bool led_initialized; 124 - struct power_supply *battery; 125 - struct power_supply *ac; 126 - struct power_supply_desc battery_desc; 127 - struct power_supply_desc ac_desc; 128 - struct kobject *remote_dir; 129 - struct attribute_group remote_group[5]; 177 + struct wacom_battery battery; 178 + bool resources; 130 179 }; 131 180 132 - static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) 181 + static inline void wacom_schedule_work(struct wacom_wac *wacom_wac, 182 + enum wacom_worker which) 133 183 { 134 184 struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); 135 - schedule_work(&wacom->work); 185 + 186 + switch (which) { 187 + case WACOM_WORKER_WIRELESS: 188 + schedule_work(&wacom->wireless_work); 189 + break; 190 + case WACOM_WORKER_BATTERY: 191 + schedule_work(&wacom->battery_work); 192 + break; 193 + case WACOM_WORKER_REMOTE: 194 + schedule_work(&wacom->remote_work); 195 + break; 196 + } 136 197 } 137 198 138 199 extern const struct hid_device_id wacom_ids[]; ··· 214 149 struct hid_usage *usage, __s32 value); 215 150 void wacom_wac_report(struct hid_device *hdev, struct hid_report *report); 216 151 void wacom_battery_work(struct work_struct *work); 217 - int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, 218 - int index); 219 - void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial); 152 + enum led_brightness wacom_leds_brightness_get(struct wacom_led *led); 153 + struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group, 154 + unsigned int id); 155 + struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur); 220 156 #endif
+853 -336
drivers/hid/wacom_sys.c
··· 25 25 #define WAC_CMD_RETRIES 10 26 26 #define WAC_CMD_DELETE_PAIRING 0x20 27 27 #define WAC_CMD_UNPAIR_ALL 0xFF 28 - #define WAC_REMOTE_SERIAL_MAX_STRLEN 9 29 28 30 29 #define DEV_ATTR_RW_PERM (S_IRUGO | S_IWUSR | S_IWGRP) 31 30 #define DEV_ATTR_WO_PERM (S_IWUSR | S_IWGRP) ··· 90 91 { 91 92 struct wacom *wacom = input_get_drvdata(dev); 92 93 93 - hid_hw_close(wacom->hdev); 94 + /* 95 + * wacom->hdev should never be null, but surprisingly, I had the case 96 + * once while unplugging the Wacom Wireless Receiver. 97 + */ 98 + if (wacom->hdev) 99 + hid_hw_close(wacom->hdev); 94 100 } 95 101 96 102 /* ··· 527 523 static LIST_HEAD(wacom_udev_list); 528 524 static DEFINE_MUTEX(wacom_udev_list_lock); 529 525 526 + static bool compare_device_paths(struct hid_device *hdev_a, 527 + struct hid_device *hdev_b, char separator) 528 + { 529 + int n1 = strrchr(hdev_a->phys, separator) - hdev_a->phys; 530 + int n2 = strrchr(hdev_b->phys, separator) - hdev_b->phys; 531 + 532 + if (n1 != n2 || n1 <= 0 || n2 <= 0) 533 + return false; 534 + 535 + return !strncmp(hdev_a->phys, hdev_b->phys, n1); 536 + } 537 + 530 538 static bool wacom_are_sibling(struct hid_device *hdev, 531 539 struct hid_device *sibling) 532 540 { 533 541 struct wacom *wacom = hid_get_drvdata(hdev); 534 542 struct wacom_features *features = &wacom->wacom_wac.features; 535 - int vid = features->oVid; 536 - int pid = features->oPid; 537 - int n1,n2; 543 + struct wacom *sibling_wacom = hid_get_drvdata(sibling); 544 + struct wacom_features *sibling_features = &sibling_wacom->wacom_wac.features; 545 + __u32 oVid = features->oVid ? features->oVid : hdev->vendor; 546 + __u32 oPid = features->oPid ? features->oPid : hdev->product; 538 547 539 - if (vid == 0 && pid == 0) { 540 - vid = hdev->vendor; 541 - pid = hdev->product; 548 + /* The defined oVid/oPid must match that of the sibling */ 549 + if (features->oVid != HID_ANY_ID && sibling->vendor != oVid) 550 + return false; 551 + if (features->oPid != HID_ANY_ID && sibling->product != oPid) 552 + return false; 553 + 554 + /* 555 + * Devices with the same VID/PID must share the same physical 556 + * device path, while those with different VID/PID must share 557 + * the same physical parent device path. 558 + */ 559 + if (hdev->vendor == sibling->vendor && hdev->product == sibling->product) { 560 + if (!compare_device_paths(hdev, sibling, '/')) 561 + return false; 562 + } else { 563 + if (!compare_device_paths(hdev, sibling, '.')) 564 + return false; 542 565 } 543 566 544 - if (vid != sibling->vendor || pid != sibling->product) 567 + /* Skip the remaining heuristics unless you are a HID_GENERIC device */ 568 + if (features->type != HID_GENERIC) 569 + return true; 570 + 571 + /* 572 + * Direct-input devices may not be siblings of indirect-input 573 + * devices. 574 + */ 575 + if ((features->device_type & WACOM_DEVICETYPE_DIRECT) && 576 + !(sibling_features->device_type & WACOM_DEVICETYPE_DIRECT)) 545 577 return false; 546 578 547 - /* Compare the physical path. */ 548 - n1 = strrchr(hdev->phys, '.') - hdev->phys; 549 - n2 = strrchr(sibling->phys, '.') - sibling->phys; 550 - if (n1 != n2 || n1 <= 0 || n2 <= 0) 579 + /* 580 + * Indirect-input devices may not be siblings of direct-input 581 + * devices. 582 + */ 583 + if (!(features->device_type & WACOM_DEVICETYPE_DIRECT) && 584 + (sibling_features->device_type & WACOM_DEVICETYPE_DIRECT)) 551 585 return false; 552 586 553 - return !strncmp(hdev->phys, sibling->phys, n1); 587 + /* Pen devices may only be siblings of touch devices */ 588 + if ((features->device_type & WACOM_DEVICETYPE_PEN) && 589 + !(sibling_features->device_type & WACOM_DEVICETYPE_TOUCH)) 590 + return false; 591 + 592 + /* Touch devices may only be siblings of pen devices */ 593 + if ((features->device_type & WACOM_DEVICETYPE_TOUCH) && 594 + !(sibling_features->device_type & WACOM_DEVICETYPE_PEN)) 595 + return false; 596 + 597 + /* 598 + * No reason could be found for these two devices to NOT be 599 + * siblings, so there's a good chance they ARE siblings 600 + */ 601 + return true; 554 602 } 555 603 556 604 static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev) 557 605 { 558 606 struct wacom_hdev_data *data; 559 607 608 + /* Try to find an already-probed interface from the same device */ 609 + list_for_each_entry(data, &wacom_udev_list, list) { 610 + if (compare_device_paths(hdev, data->dev, '/')) 611 + return data; 612 + } 613 + 614 + /* Fallback to finding devices that appear to be "siblings" */ 560 615 list_for_each_entry(data, &wacom_udev_list, list) { 561 616 if (wacom_are_sibling(hdev, data->dev)) { 562 617 kref_get(&data->kref); ··· 624 561 } 625 562 626 563 return NULL; 564 + } 565 + 566 + static void wacom_release_shared_data(struct kref *kref) 567 + { 568 + struct wacom_hdev_data *data = 569 + container_of(kref, struct wacom_hdev_data, kref); 570 + 571 + mutex_lock(&wacom_udev_list_lock); 572 + list_del(&data->list); 573 + mutex_unlock(&wacom_udev_list_lock); 574 + 575 + kfree(data); 576 + } 577 + 578 + static void wacom_remove_shared_data(void *res) 579 + { 580 + struct wacom *wacom = res; 581 + struct wacom_hdev_data *data; 582 + struct wacom_wac *wacom_wac = &wacom->wacom_wac; 583 + 584 + if (wacom_wac->shared) { 585 + data = container_of(wacom_wac->shared, struct wacom_hdev_data, 586 + shared); 587 + 588 + if (wacom_wac->shared->touch == wacom->hdev) 589 + wacom_wac->shared->touch = NULL; 590 + else if (wacom_wac->shared->pen == wacom->hdev) 591 + wacom_wac->shared->pen = NULL; 592 + 593 + kref_put(&data->kref, wacom_release_shared_data); 594 + wacom_wac->shared = NULL; 595 + } 627 596 } 628 597 629 598 static int wacom_add_shared_data(struct hid_device *hdev) ··· 682 587 683 588 wacom_wac->shared = &data->shared; 684 589 590 + retval = devm_add_action(&hdev->dev, wacom_remove_shared_data, wacom); 591 + if (retval) { 592 + mutex_unlock(&wacom_udev_list_lock); 593 + wacom_remove_shared_data(wacom); 594 + return retval; 595 + } 596 + 685 597 if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) 686 598 wacom_wac->shared->touch = hdev; 687 599 else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) ··· 699 597 return retval; 700 598 } 701 599 702 - static void wacom_release_shared_data(struct kref *kref) 703 - { 704 - struct wacom_hdev_data *data = 705 - container_of(kref, struct wacom_hdev_data, kref); 706 - 707 - mutex_lock(&wacom_udev_list_lock); 708 - list_del(&data->list); 709 - mutex_unlock(&wacom_udev_list_lock); 710 - 711 - kfree(data); 712 - } 713 - 714 - static void wacom_remove_shared_data(struct wacom *wacom) 715 - { 716 - struct wacom_hdev_data *data; 717 - struct wacom_wac *wacom_wac = &wacom->wacom_wac; 718 - 719 - if (wacom_wac->shared) { 720 - data = container_of(wacom_wac->shared, struct wacom_hdev_data, 721 - shared); 722 - 723 - if (wacom_wac->shared->touch == wacom->hdev) 724 - wacom_wac->shared->touch = NULL; 725 - else if (wacom_wac->shared->pen == wacom->hdev) 726 - wacom_wac->shared->pen = NULL; 727 - 728 - kref_put(&data->kref, wacom_release_shared_data); 729 - wacom_wac->shared = NULL; 730 - } 731 - } 732 - 733 600 static int wacom_led_control(struct wacom *wacom) 734 601 { 735 602 unsigned char *buf; 736 603 int retval; 737 604 unsigned char report_id = WAC_CMD_LED_CONTROL; 738 605 int buf_size = 9; 606 + 607 + if (!hid_get_drvdata(wacom->hdev)) 608 + return -ENODEV; 609 + 610 + if (!wacom->led.groups) 611 + return -ENOTSUPP; 739 612 740 613 if (wacom->wacom_wac.pid) { /* wireless connected */ 741 614 report_id = WAC_CMD_WL_LED_CONTROL; ··· 727 650 * one of four values: 728 651 * 0 = Low; 1 = Medium; 2 = High; 3 = Off 729 652 */ 730 - int ring_led = wacom->led.select[0] & 0x03; 653 + int ring_led = wacom->led.groups[0].select & 0x03; 731 654 int ring_lum = (((wacom->led.llv & 0x60) >> 5) - 1) & 0x03; 732 655 int crop_lum = 0; 733 656 unsigned char led_bits = (crop_lum << 4) | (ring_lum << 2) | (ring_led); ··· 742 665 buf[1] = led_bits; 743 666 } 744 667 else { 745 - int led = wacom->led.select[0] | 0x4; 668 + int led = wacom->led.groups[0].select | 0x4; 746 669 747 670 if (wacom->wacom_wac.features.type == WACOM_21UX2 || 748 671 wacom->wacom_wac.features.type == WACOM_24HD) 749 - led |= (wacom->led.select[1] << 4) | 0x40; 672 + led |= (wacom->led.groups[1].select << 4) | 0x40; 750 673 751 674 buf[0] = report_id; 752 675 buf[1] = led; ··· 818 741 819 742 mutex_lock(&wacom->lock); 820 743 821 - wacom->led.select[set_id] = id & 0x3; 744 + wacom->led.groups[set_id].select = id & 0x3; 822 745 err = wacom_led_control(wacom); 823 746 824 747 mutex_unlock(&wacom->lock); ··· 838 761 struct hid_device *hdev = to_hid_device(dev);\ 839 762 struct wacom *wacom = hid_get_drvdata(hdev); \ 840 763 return scnprintf(buf, PAGE_SIZE, "%d\n", \ 841 - wacom->led.select[SET_ID]); \ 764 + wacom->led.groups[SET_ID].select); \ 842 765 } \ 843 766 static DEVICE_ATTR(status_led##SET_ID##_select, DEV_ATTR_RW_PERM, \ 844 767 wacom_led##SET_ID##_select_show, \ ··· 981 904 .attrs = intuos5_led_attrs, 982 905 }; 983 906 907 + struct wacom_sysfs_group_devres { 908 + struct attribute_group *group; 909 + struct kobject *root; 910 + }; 911 + 912 + static void wacom_devm_sysfs_group_release(struct device *dev, void *res) 913 + { 914 + struct wacom_sysfs_group_devres *devres = res; 915 + struct kobject *kobj = devres->root; 916 + 917 + dev_dbg(dev, "%s: dropping reference to %s\n", 918 + __func__, devres->group->name); 919 + sysfs_remove_group(kobj, devres->group); 920 + } 921 + 922 + static int __wacom_devm_sysfs_create_group(struct wacom *wacom, 923 + struct kobject *root, 924 + struct attribute_group *group) 925 + { 926 + struct wacom_sysfs_group_devres *devres; 927 + int error; 928 + 929 + devres = devres_alloc(wacom_devm_sysfs_group_release, 930 + sizeof(struct wacom_sysfs_group_devres), 931 + GFP_KERNEL); 932 + if (!devres) 933 + return -ENOMEM; 934 + 935 + devres->group = group; 936 + devres->root = root; 937 + 938 + error = sysfs_create_group(devres->root, group); 939 + if (error) 940 + return error; 941 + 942 + devres_add(&wacom->hdev->dev, devres); 943 + 944 + return 0; 945 + } 946 + 947 + static int wacom_devm_sysfs_create_group(struct wacom *wacom, 948 + struct attribute_group *group) 949 + { 950 + return __wacom_devm_sysfs_create_group(wacom, &wacom->hdev->dev.kobj, 951 + group); 952 + } 953 + 954 + enum led_brightness wacom_leds_brightness_get(struct wacom_led *led) 955 + { 956 + struct wacom *wacom = led->wacom; 957 + 958 + if (wacom->led.max_hlv) 959 + return led->hlv * LED_FULL / wacom->led.max_hlv; 960 + 961 + if (wacom->led.max_llv) 962 + return led->llv * LED_FULL / wacom->led.max_llv; 963 + 964 + /* device doesn't support brightness tuning */ 965 + return LED_FULL; 966 + } 967 + 968 + static enum led_brightness __wacom_led_brightness_get(struct led_classdev *cdev) 969 + { 970 + struct wacom_led *led = container_of(cdev, struct wacom_led, cdev); 971 + struct wacom *wacom = led->wacom; 972 + 973 + if (wacom->led.groups[led->group].select != led->id) 974 + return LED_OFF; 975 + 976 + return wacom_leds_brightness_get(led); 977 + } 978 + 979 + static int wacom_led_brightness_set(struct led_classdev *cdev, 980 + enum led_brightness brightness) 981 + { 982 + struct wacom_led *led = container_of(cdev, struct wacom_led, cdev); 983 + struct wacom *wacom = led->wacom; 984 + int error; 985 + 986 + mutex_lock(&wacom->lock); 987 + 988 + if (!wacom->led.groups || (brightness == LED_OFF && 989 + wacom->led.groups[led->group].select != led->id)) { 990 + error = 0; 991 + goto out; 992 + } 993 + 994 + led->llv = wacom->led.llv = wacom->led.max_llv * brightness / LED_FULL; 995 + led->hlv = wacom->led.hlv = wacom->led.max_hlv * brightness / LED_FULL; 996 + 997 + wacom->led.groups[led->group].select = led->id; 998 + 999 + error = wacom_led_control(wacom); 1000 + 1001 + out: 1002 + mutex_unlock(&wacom->lock); 1003 + 1004 + return error; 1005 + } 1006 + 1007 + static void wacom_led_readonly_brightness_set(struct led_classdev *cdev, 1008 + enum led_brightness brightness) 1009 + { 1010 + } 1011 + 1012 + static int wacom_led_register_one(struct device *dev, struct wacom *wacom, 1013 + struct wacom_led *led, unsigned int group, 1014 + unsigned int id, bool read_only) 1015 + { 1016 + int error; 1017 + char *name; 1018 + 1019 + name = devm_kasprintf(dev, GFP_KERNEL, 1020 + "%s::wacom-%d.%d", 1021 + dev_name(dev), 1022 + group, 1023 + id); 1024 + if (!name) 1025 + return -ENOMEM; 1026 + 1027 + if (!read_only) { 1028 + led->trigger.name = name; 1029 + error = devm_led_trigger_register(dev, &led->trigger); 1030 + if (error) { 1031 + hid_err(wacom->hdev, 1032 + "failed to register LED trigger %s: %d\n", 1033 + led->cdev.name, error); 1034 + return error; 1035 + } 1036 + } 1037 + 1038 + led->group = group; 1039 + led->id = id; 1040 + led->wacom = wacom; 1041 + led->llv = wacom->led.llv; 1042 + led->hlv = wacom->led.hlv; 1043 + led->cdev.name = name; 1044 + led->cdev.max_brightness = LED_FULL; 1045 + led->cdev.flags = LED_HW_PLUGGABLE; 1046 + led->cdev.brightness_get = __wacom_led_brightness_get; 1047 + if (!read_only) { 1048 + led->cdev.brightness_set_blocking = wacom_led_brightness_set; 1049 + led->cdev.default_trigger = led->cdev.name; 1050 + } else { 1051 + led->cdev.brightness_set = wacom_led_readonly_brightness_set; 1052 + } 1053 + 1054 + error = devm_led_classdev_register(dev, &led->cdev); 1055 + if (error) { 1056 + hid_err(wacom->hdev, 1057 + "failed to register LED %s: %d\n", 1058 + led->cdev.name, error); 1059 + led->cdev.name = NULL; 1060 + return error; 1061 + } 1062 + 1063 + return 0; 1064 + } 1065 + 1066 + static void wacom_led_groups_release_one(void *data) 1067 + { 1068 + struct wacom_group_leds *group = data; 1069 + 1070 + devres_release_group(group->dev, group); 1071 + } 1072 + 1073 + static int wacom_led_groups_alloc_and_register_one(struct device *dev, 1074 + struct wacom *wacom, 1075 + int group_id, int count, 1076 + bool read_only) 1077 + { 1078 + struct wacom_led *leds; 1079 + int i, error; 1080 + 1081 + if (group_id >= wacom->led.count || count <= 0) 1082 + return -EINVAL; 1083 + 1084 + if (!devres_open_group(dev, &wacom->led.groups[group_id], GFP_KERNEL)) 1085 + return -ENOMEM; 1086 + 1087 + leds = devm_kzalloc(dev, sizeof(struct wacom_led) * count, GFP_KERNEL); 1088 + if (!leds) { 1089 + error = -ENOMEM; 1090 + goto err; 1091 + } 1092 + 1093 + wacom->led.groups[group_id].leds = leds; 1094 + wacom->led.groups[group_id].count = count; 1095 + 1096 + for (i = 0; i < count; i++) { 1097 + error = wacom_led_register_one(dev, wacom, &leds[i], 1098 + group_id, i, read_only); 1099 + if (error) 1100 + goto err; 1101 + } 1102 + 1103 + wacom->led.groups[group_id].dev = dev; 1104 + 1105 + devres_close_group(dev, &wacom->led.groups[group_id]); 1106 + 1107 + /* 1108 + * There is a bug (?) in devm_led_classdev_register() in which its 1109 + * increments the refcount of the parent. If the parent is an input 1110 + * device, that means the ref count never reaches 0 when 1111 + * devm_input_device_release() gets called. 1112 + * This means that the LEDs are still there after disconnect. 1113 + * Manually force the release of the group so that the leds are released 1114 + * once we are done using them. 1115 + */ 1116 + error = devm_add_action_or_reset(&wacom->hdev->dev, 1117 + wacom_led_groups_release_one, 1118 + &wacom->led.groups[group_id]); 1119 + if (error) 1120 + return error; 1121 + 1122 + return 0; 1123 + 1124 + err: 1125 + devres_release_group(dev, &wacom->led.groups[group_id]); 1126 + return error; 1127 + } 1128 + 1129 + struct wacom_led *wacom_led_find(struct wacom *wacom, unsigned int group_id, 1130 + unsigned int id) 1131 + { 1132 + struct wacom_group_leds *group; 1133 + 1134 + if (group_id >= wacom->led.count) 1135 + return NULL; 1136 + 1137 + group = &wacom->led.groups[group_id]; 1138 + 1139 + if (!group->leds) 1140 + return NULL; 1141 + 1142 + id %= group->count; 1143 + 1144 + return &group->leds[id]; 1145 + } 1146 + 1147 + /** 1148 + * wacom_led_next: gives the next available led with a wacom trigger. 1149 + * 1150 + * returns the next available struct wacom_led which has its default trigger 1151 + * or the current one if none is available. 1152 + */ 1153 + struct wacom_led *wacom_led_next(struct wacom *wacom, struct wacom_led *cur) 1154 + { 1155 + struct wacom_led *next_led; 1156 + int group, next; 1157 + 1158 + if (!wacom || !cur) 1159 + return NULL; 1160 + 1161 + group = cur->group; 1162 + next = cur->id; 1163 + 1164 + do { 1165 + next_led = wacom_led_find(wacom, group, ++next); 1166 + if (!next_led || next_led == cur) 1167 + return next_led; 1168 + } while (next_led->cdev.trigger != &next_led->trigger); 1169 + 1170 + return next_led; 1171 + } 1172 + 1173 + static void wacom_led_groups_release(void *data) 1174 + { 1175 + struct wacom *wacom = data; 1176 + 1177 + wacom->led.groups = NULL; 1178 + wacom->led.count = 0; 1179 + } 1180 + 1181 + static int wacom_led_groups_allocate(struct wacom *wacom, int count) 1182 + { 1183 + struct device *dev = &wacom->hdev->dev; 1184 + struct wacom_group_leds *groups; 1185 + int error; 1186 + 1187 + groups = devm_kzalloc(dev, sizeof(struct wacom_group_leds) * count, 1188 + GFP_KERNEL); 1189 + if (!groups) 1190 + return -ENOMEM; 1191 + 1192 + error = devm_add_action_or_reset(dev, wacom_led_groups_release, wacom); 1193 + if (error) 1194 + return error; 1195 + 1196 + wacom->led.groups = groups; 1197 + wacom->led.count = count; 1198 + 1199 + return 0; 1200 + } 1201 + 1202 + static int wacom_leds_alloc_and_register(struct wacom *wacom, int group_count, 1203 + int led_per_group, bool read_only) 1204 + { 1205 + struct device *dev; 1206 + int i, error; 1207 + 1208 + if (!wacom->wacom_wac.pad_input) 1209 + return -EINVAL; 1210 + 1211 + dev = &wacom->wacom_wac.pad_input->dev; 1212 + 1213 + error = wacom_led_groups_allocate(wacom, group_count); 1214 + if (error) 1215 + return error; 1216 + 1217 + for (i = 0; i < group_count; i++) { 1218 + error = wacom_led_groups_alloc_and_register_one(dev, wacom, i, 1219 + led_per_group, 1220 + read_only); 1221 + if (error) 1222 + return error; 1223 + } 1224 + 1225 + return 0; 1226 + } 1227 + 984 1228 static int wacom_initialize_leds(struct wacom *wacom) 985 1229 { 986 1230 int error; ··· 1315 917 case INTUOS4: 1316 918 case INTUOS4WL: 1317 919 case INTUOS4L: 1318 - wacom->led.select[0] = 0; 1319 - wacom->led.select[1] = 0; 1320 920 wacom->led.llv = 10; 1321 921 wacom->led.hlv = 20; 922 + wacom->led.max_llv = 127; 923 + wacom->led.max_hlv = 127; 1322 924 wacom->led.img_lum = 10; 1323 - error = sysfs_create_group(&wacom->hdev->dev.kobj, 1324 - &intuos4_led_attr_group); 925 + 926 + error = wacom_leds_alloc_and_register(wacom, 1, 4, false); 927 + if (error) { 928 + hid_err(wacom->hdev, 929 + "cannot create leds err: %d\n", error); 930 + return error; 931 + } 932 + 933 + error = wacom_devm_sysfs_create_group(wacom, 934 + &intuos4_led_attr_group); 1325 935 break; 1326 936 1327 937 case WACOM_24HD: 1328 938 case WACOM_21UX2: 1329 - wacom->led.select[0] = 0; 1330 - wacom->led.select[1] = 0; 1331 939 wacom->led.llv = 0; 1332 940 wacom->led.hlv = 0; 1333 941 wacom->led.img_lum = 0; 1334 942 1335 - error = sysfs_create_group(&wacom->hdev->dev.kobj, 1336 - &cintiq_led_attr_group); 943 + error = wacom_leds_alloc_and_register(wacom, 2, 4, false); 944 + if (error) { 945 + hid_err(wacom->hdev, 946 + "cannot create leds err: %d\n", error); 947 + return error; 948 + } 949 + 950 + error = wacom_devm_sysfs_create_group(wacom, 951 + &cintiq_led_attr_group); 1337 952 break; 1338 953 1339 954 case INTUOS5S: ··· 1355 944 case INTUOSPS: 1356 945 case INTUOSPM: 1357 946 case INTUOSPL: 1358 - wacom->led.select[0] = 0; 1359 - wacom->led.select[1] = 0; 1360 947 wacom->led.llv = 32; 1361 - wacom->led.hlv = 0; 1362 - wacom->led.img_lum = 0; 948 + wacom->led.max_llv = 96; 1363 949 1364 - error = sysfs_create_group(&wacom->hdev->dev.kobj, 1365 - &intuos5_led_attr_group); 950 + error = wacom_leds_alloc_and_register(wacom, 1, 4, false); 951 + if (error) { 952 + hid_err(wacom->hdev, 953 + "cannot create leds err: %d\n", error); 954 + return error; 955 + } 956 + 957 + error = wacom_devm_sysfs_create_group(wacom, 958 + &intuos5_led_attr_group); 1366 959 break; 960 + 961 + case REMOTE: 962 + wacom->led.llv = 255; 963 + wacom->led.max_llv = 255; 964 + error = wacom_led_groups_allocate(wacom, 5); 965 + if (error) { 966 + hid_err(wacom->hdev, 967 + "cannot create leds err: %d\n", error); 968 + return error; 969 + } 970 + return 0; 1367 971 1368 972 default: 1369 973 return 0; ··· 1390 964 return error; 1391 965 } 1392 966 wacom_led_control(wacom); 1393 - wacom->led_initialized = true; 1394 967 1395 968 return 0; 1396 969 } 1397 970 1398 - static void wacom_destroy_leds(struct wacom *wacom) 1399 - { 1400 - if (!wacom->led_initialized) 1401 - return; 1402 - 1403 - if (!(wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PAD)) 1404 - return; 1405 - 1406 - wacom->led_initialized = false; 1407 - 1408 - switch (wacom->wacom_wac.features.type) { 1409 - case INTUOS4S: 1410 - case INTUOS4: 1411 - case INTUOS4WL: 1412 - case INTUOS4L: 1413 - sysfs_remove_group(&wacom->hdev->dev.kobj, 1414 - &intuos4_led_attr_group); 1415 - break; 1416 - 1417 - case WACOM_24HD: 1418 - case WACOM_21UX2: 1419 - sysfs_remove_group(&wacom->hdev->dev.kobj, 1420 - &cintiq_led_attr_group); 1421 - break; 1422 - 1423 - case INTUOS5S: 1424 - case INTUOS5: 1425 - case INTUOS5L: 1426 - case INTUOSPS: 1427 - case INTUOSPM: 1428 - case INTUOSPL: 1429 - sysfs_remove_group(&wacom->hdev->dev.kobj, 1430 - &intuos5_led_attr_group); 1431 - break; 1432 - } 1433 - } 1434 - 1435 971 static enum power_supply_property wacom_battery_props[] = { 972 + POWER_SUPPLY_PROP_MODEL_NAME, 1436 973 POWER_SUPPLY_PROP_PRESENT, 1437 974 POWER_SUPPLY_PROP_STATUS, 1438 975 POWER_SUPPLY_PROP_SCOPE, 1439 976 POWER_SUPPLY_PROP_CAPACITY 1440 977 }; 1441 978 1442 - static enum power_supply_property wacom_ac_props[] = { 1443 - POWER_SUPPLY_PROP_PRESENT, 1444 - POWER_SUPPLY_PROP_ONLINE, 1445 - POWER_SUPPLY_PROP_SCOPE, 1446 - }; 1447 - 1448 979 static int wacom_battery_get_property(struct power_supply *psy, 1449 980 enum power_supply_property psp, 1450 981 union power_supply_propval *val) 1451 982 { 1452 - struct wacom *wacom = power_supply_get_drvdata(psy); 983 + struct wacom_battery *battery = power_supply_get_drvdata(psy); 1453 984 int ret = 0; 1454 985 1455 986 switch (psp) { 987 + case POWER_SUPPLY_PROP_MODEL_NAME: 988 + val->strval = battery->wacom->wacom_wac.name; 989 + break; 1456 990 case POWER_SUPPLY_PROP_PRESENT: 1457 - val->intval = wacom->wacom_wac.bat_connected; 991 + val->intval = battery->bat_connected; 1458 992 break; 1459 993 case POWER_SUPPLY_PROP_SCOPE: 1460 994 val->intval = POWER_SUPPLY_SCOPE_DEVICE; 1461 995 break; 1462 996 case POWER_SUPPLY_PROP_CAPACITY: 1463 - val->intval = 1464 - wacom->wacom_wac.battery_capacity; 997 + val->intval = battery->battery_capacity; 1465 998 break; 1466 999 case POWER_SUPPLY_PROP_STATUS: 1467 - if (wacom->wacom_wac.bat_charging) 1000 + if (battery->bat_charging) 1468 1001 val->intval = POWER_SUPPLY_STATUS_CHARGING; 1469 - else if (wacom->wacom_wac.battery_capacity == 100 && 1470 - wacom->wacom_wac.ps_connected) 1002 + else if (battery->battery_capacity == 100 && 1003 + battery->ps_connected) 1471 1004 val->intval = POWER_SUPPLY_STATUS_FULL; 1472 - else if (wacom->wacom_wac.ps_connected) 1005 + else if (battery->ps_connected) 1473 1006 val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; 1474 1007 else 1475 1008 val->intval = POWER_SUPPLY_STATUS_DISCHARGING; ··· 1441 1056 return ret; 1442 1057 } 1443 1058 1444 - static int wacom_ac_get_property(struct power_supply *psy, 1445 - enum power_supply_property psp, 1446 - union power_supply_propval *val) 1059 + static int __wacom_initialize_battery(struct wacom *wacom, 1060 + struct wacom_battery *battery) 1447 1061 { 1448 - struct wacom *wacom = power_supply_get_drvdata(psy); 1449 - int ret = 0; 1062 + static atomic_t battery_no = ATOMIC_INIT(0); 1063 + struct device *dev = &wacom->hdev->dev; 1064 + struct power_supply_config psy_cfg = { .drv_data = battery, }; 1065 + struct power_supply *ps_bat; 1066 + struct power_supply_desc *bat_desc = &battery->bat_desc; 1067 + unsigned long n; 1068 + int error; 1450 1069 1451 - switch (psp) { 1452 - case POWER_SUPPLY_PROP_PRESENT: 1453 - /* fall through */ 1454 - case POWER_SUPPLY_PROP_ONLINE: 1455 - val->intval = wacom->wacom_wac.ps_connected; 1456 - break; 1457 - case POWER_SUPPLY_PROP_SCOPE: 1458 - val->intval = POWER_SUPPLY_SCOPE_DEVICE; 1459 - break; 1460 - default: 1461 - ret = -EINVAL; 1462 - break; 1070 + if (!devres_open_group(dev, bat_desc, GFP_KERNEL)) 1071 + return -ENOMEM; 1072 + 1073 + battery->wacom = wacom; 1074 + 1075 + n = atomic_inc_return(&battery_no) - 1; 1076 + 1077 + bat_desc->properties = wacom_battery_props; 1078 + bat_desc->num_properties = ARRAY_SIZE(wacom_battery_props); 1079 + bat_desc->get_property = wacom_battery_get_property; 1080 + sprintf(battery->bat_name, "wacom_battery_%ld", n); 1081 + bat_desc->name = battery->bat_name; 1082 + bat_desc->type = POWER_SUPPLY_TYPE_USB; 1083 + bat_desc->use_for_apm = 0; 1084 + 1085 + ps_bat = devm_power_supply_register(dev, bat_desc, &psy_cfg); 1086 + if (IS_ERR(ps_bat)) { 1087 + error = PTR_ERR(ps_bat); 1088 + goto err; 1463 1089 } 1464 - return ret; 1090 + 1091 + power_supply_powers(ps_bat, &wacom->hdev->dev); 1092 + 1093 + battery->battery = ps_bat; 1094 + 1095 + devres_close_group(dev, bat_desc); 1096 + return 0; 1097 + 1098 + err: 1099 + devres_release_group(dev, bat_desc); 1100 + return error; 1465 1101 } 1466 1102 1467 1103 static int wacom_initialize_battery(struct wacom *wacom) 1468 1104 { 1469 - static atomic_t battery_no = ATOMIC_INIT(0); 1470 - struct power_supply_config psy_cfg = { .drv_data = wacom, }; 1471 - unsigned long n; 1472 - 1473 - if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) { 1474 - struct power_supply_desc *bat_desc = &wacom->battery_desc; 1475 - struct power_supply_desc *ac_desc = &wacom->ac_desc; 1476 - n = atomic_inc_return(&battery_no) - 1; 1477 - 1478 - bat_desc->properties = wacom_battery_props; 1479 - bat_desc->num_properties = ARRAY_SIZE(wacom_battery_props); 1480 - bat_desc->get_property = wacom_battery_get_property; 1481 - sprintf(wacom->wacom_wac.bat_name, "wacom_battery_%ld", n); 1482 - bat_desc->name = wacom->wacom_wac.bat_name; 1483 - bat_desc->type = POWER_SUPPLY_TYPE_BATTERY; 1484 - bat_desc->use_for_apm = 0; 1485 - 1486 - ac_desc->properties = wacom_ac_props; 1487 - ac_desc->num_properties = ARRAY_SIZE(wacom_ac_props); 1488 - ac_desc->get_property = wacom_ac_get_property; 1489 - sprintf(wacom->wacom_wac.ac_name, "wacom_ac_%ld", n); 1490 - ac_desc->name = wacom->wacom_wac.ac_name; 1491 - ac_desc->type = POWER_SUPPLY_TYPE_MAINS; 1492 - ac_desc->use_for_apm = 0; 1493 - 1494 - wacom->battery = power_supply_register(&wacom->hdev->dev, 1495 - &wacom->battery_desc, &psy_cfg); 1496 - if (IS_ERR(wacom->battery)) 1497 - return PTR_ERR(wacom->battery); 1498 - 1499 - power_supply_powers(wacom->battery, &wacom->hdev->dev); 1500 - 1501 - wacom->ac = power_supply_register(&wacom->hdev->dev, 1502 - &wacom->ac_desc, 1503 - &psy_cfg); 1504 - if (IS_ERR(wacom->ac)) { 1505 - power_supply_unregister(wacom->battery); 1506 - return PTR_ERR(wacom->ac); 1507 - } 1508 - 1509 - power_supply_powers(wacom->ac, &wacom->hdev->dev); 1510 - } 1105 + if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) 1106 + return __wacom_initialize_battery(wacom, &wacom->battery); 1511 1107 1512 1108 return 0; 1513 1109 } 1514 1110 1515 1111 static void wacom_destroy_battery(struct wacom *wacom) 1516 1112 { 1517 - if (wacom->battery) { 1518 - power_supply_unregister(wacom->battery); 1519 - wacom->battery = NULL; 1520 - power_supply_unregister(wacom->ac); 1521 - wacom->ac = NULL; 1113 + if (wacom->battery.battery) { 1114 + devres_release_group(&wacom->hdev->dev, 1115 + &wacom->battery.bat_desc); 1116 + wacom->battery.battery = NULL; 1522 1117 } 1523 1118 } 1524 1119 ··· 1544 1179 struct wacom *wacom = hid_get_drvdata(hdev); 1545 1180 u8 mode; 1546 1181 1547 - mode = wacom->led.select[index]; 1182 + mode = wacom->led.groups[index].select; 1548 1183 if (mode >= 0 && mode < 3) 1549 1184 return snprintf(buf, PAGE_SIZE, "%d\n", mode); 1550 1185 else ··· 1577 1212 DEVICE_EKR_ATTR_GROUP(3); 1578 1213 DEVICE_EKR_ATTR_GROUP(4); 1579 1214 1580 - int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, int index) 1215 + static int wacom_remote_create_attr_group(struct wacom *wacom, __u32 serial, 1216 + int index) 1581 1217 { 1582 1218 int error = 0; 1583 - char *buf; 1584 - struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1219 + struct wacom_remote *remote = wacom->remote; 1585 1220 1586 - wacom_wac->serial[index] = serial; 1587 - 1588 - buf = kzalloc(WAC_REMOTE_SERIAL_MAX_STRLEN, GFP_KERNEL); 1589 - if (!buf) 1221 + remote->remotes[index].group.name = devm_kasprintf(&wacom->hdev->dev, 1222 + GFP_KERNEL, 1223 + "%d", serial); 1224 + if (!remote->remotes[index].group.name) 1590 1225 return -ENOMEM; 1591 - snprintf(buf, WAC_REMOTE_SERIAL_MAX_STRLEN, "%d", serial); 1592 - wacom->remote_group[index].name = buf; 1593 1226 1594 - error = sysfs_create_group(wacom->remote_dir, 1595 - &wacom->remote_group[index]); 1227 + error = __wacom_devm_sysfs_create_group(wacom, remote->remote_dir, 1228 + &remote->remotes[index].group); 1596 1229 if (error) { 1230 + remote->remotes[index].group.name = NULL; 1597 1231 hid_err(wacom->hdev, 1598 1232 "cannot create sysfs group err: %d\n", error); 1599 - kobject_put(wacom->remote_dir); 1600 1233 return error; 1601 1234 } 1602 1235 1603 1236 return 0; 1604 - } 1605 - 1606 - void wacom_remote_destroy_attr_group(struct wacom *wacom, __u32 serial) 1607 - { 1608 - struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1609 - int i; 1610 - 1611 - if (!serial) 1612 - return; 1613 - 1614 - for (i = 0; i < WACOM_MAX_REMOTES; i++) { 1615 - if (wacom_wac->serial[i] == serial) { 1616 - wacom_wac->serial[i] = 0; 1617 - wacom->led.select[i] = WACOM_STATUS_UNKNOWN; 1618 - if (wacom->remote_group[i].name) { 1619 - sysfs_remove_group(wacom->remote_dir, 1620 - &wacom->remote_group[i]); 1621 - kfree(wacom->remote_group[i].name); 1622 - wacom->remote_group[i].name = NULL; 1623 - } 1624 - } 1625 - } 1626 1237 } 1627 1238 1628 1239 static int wacom_cmd_unpair_remote(struct wacom *wacom, unsigned char selector) ··· 1657 1316 NULL 1658 1317 }; 1659 1318 1660 - static int wacom_initialize_remote(struct wacom *wacom) 1319 + static void wacom_remotes_destroy(void *data) 1320 + { 1321 + struct wacom *wacom = data; 1322 + struct wacom_remote *remote = wacom->remote; 1323 + 1324 + if (!remote) 1325 + return; 1326 + 1327 + kobject_put(remote->remote_dir); 1328 + kfifo_free(&remote->remote_fifo); 1329 + wacom->remote = NULL; 1330 + } 1331 + 1332 + static int wacom_initialize_remotes(struct wacom *wacom) 1661 1333 { 1662 1334 int error = 0; 1663 - struct wacom_wac *wacom_wac = &(wacom->wacom_wac); 1335 + struct wacom_remote *remote; 1664 1336 int i; 1665 1337 1666 1338 if (wacom->wacom_wac.features.type != REMOTE) 1667 1339 return 0; 1668 1340 1669 - wacom->remote_group[0] = remote0_serial_group; 1670 - wacom->remote_group[1] = remote1_serial_group; 1671 - wacom->remote_group[2] = remote2_serial_group; 1672 - wacom->remote_group[3] = remote3_serial_group; 1673 - wacom->remote_group[4] = remote4_serial_group; 1674 - 1675 - wacom->remote_dir = kobject_create_and_add("wacom_remote", 1676 - &wacom->hdev->dev.kobj); 1677 - if (!wacom->remote_dir) 1341 + remote = devm_kzalloc(&wacom->hdev->dev, sizeof(*wacom->remote), 1342 + GFP_KERNEL); 1343 + if (!remote) 1678 1344 return -ENOMEM; 1679 1345 1680 - error = sysfs_create_files(wacom->remote_dir, remote_unpair_attrs); 1346 + wacom->remote = remote; 1347 + 1348 + spin_lock_init(&remote->remote_lock); 1349 + 1350 + error = kfifo_alloc(&remote->remote_fifo, 1351 + 5 * sizeof(struct wacom_remote_data), 1352 + GFP_KERNEL); 1353 + if (error) { 1354 + hid_err(wacom->hdev, "failed allocating remote_fifo\n"); 1355 + return -ENOMEM; 1356 + } 1357 + 1358 + remote->remotes[0].group = remote0_serial_group; 1359 + remote->remotes[1].group = remote1_serial_group; 1360 + remote->remotes[2].group = remote2_serial_group; 1361 + remote->remotes[3].group = remote3_serial_group; 1362 + remote->remotes[4].group = remote4_serial_group; 1363 + 1364 + remote->remote_dir = kobject_create_and_add("wacom_remote", 1365 + &wacom->hdev->dev.kobj); 1366 + if (!remote->remote_dir) 1367 + return -ENOMEM; 1368 + 1369 + error = sysfs_create_files(remote->remote_dir, remote_unpair_attrs); 1681 1370 1682 1371 if (error) { 1683 1372 hid_err(wacom->hdev, ··· 1716 1345 } 1717 1346 1718 1347 for (i = 0; i < WACOM_MAX_REMOTES; i++) { 1719 - wacom->led.select[i] = WACOM_STATUS_UNKNOWN; 1720 - wacom_wac->serial[i] = 0; 1348 + wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN; 1349 + remote->remotes[i].serial = 0; 1721 1350 } 1351 + 1352 + error = devm_add_action_or_reset(&wacom->hdev->dev, 1353 + wacom_remotes_destroy, wacom); 1354 + if (error) 1355 + return error; 1722 1356 1723 1357 return 0; 1724 1358 } ··· 1734 1358 struct hid_device *hdev = wacom->hdev; 1735 1359 struct wacom_wac *wacom_wac = &(wacom->wacom_wac); 1736 1360 1737 - input_dev = input_allocate_device(); 1361 + input_dev = devm_input_allocate_device(&hdev->dev); 1738 1362 if (!input_dev) 1739 1363 return NULL; 1740 1364 ··· 1753 1377 return input_dev; 1754 1378 } 1755 1379 1756 - static void wacom_clean_inputs(struct wacom *wacom) 1757 - { 1758 - if (wacom->wacom_wac.pen_input) { 1759 - if (wacom->wacom_wac.pen_registered) 1760 - input_unregister_device(wacom->wacom_wac.pen_input); 1761 - else 1762 - input_free_device(wacom->wacom_wac.pen_input); 1763 - } 1764 - if (wacom->wacom_wac.touch_input) { 1765 - if (wacom->wacom_wac.touch_registered) 1766 - input_unregister_device(wacom->wacom_wac.touch_input); 1767 - else 1768 - input_free_device(wacom->wacom_wac.touch_input); 1769 - } 1770 - if (wacom->wacom_wac.pad_input) { 1771 - if (wacom->wacom_wac.pad_registered) 1772 - input_unregister_device(wacom->wacom_wac.pad_input); 1773 - else 1774 - input_free_device(wacom->wacom_wac.pad_input); 1775 - } 1776 - kobject_put(wacom->remote_dir); 1777 - wacom->wacom_wac.pen_input = NULL; 1778 - wacom->wacom_wac.touch_input = NULL; 1779 - wacom->wacom_wac.pad_input = NULL; 1780 - wacom->wacom_wac.pen_registered = false; 1781 - wacom->wacom_wac.touch_registered = false; 1782 - wacom->wacom_wac.pad_registered = false; 1783 - wacom_destroy_leds(wacom); 1784 - } 1785 - 1786 1380 static int wacom_allocate_inputs(struct wacom *wacom) 1787 1381 { 1788 1382 struct wacom_wac *wacom_wac = &(wacom->wacom_wac); ··· 1760 1414 wacom_wac->pen_input = wacom_allocate_input(wacom); 1761 1415 wacom_wac->touch_input = wacom_allocate_input(wacom); 1762 1416 wacom_wac->pad_input = wacom_allocate_input(wacom); 1763 - if (!wacom_wac->pen_input || !wacom_wac->touch_input || !wacom_wac->pad_input) { 1764 - wacom_clean_inputs(wacom); 1417 + if (!wacom_wac->pen_input || 1418 + !wacom_wac->touch_input || 1419 + !wacom_wac->pad_input) 1765 1420 return -ENOMEM; 1766 - } 1767 1421 1768 1422 wacom_wac->pen_input->name = wacom_wac->pen_name; 1769 1423 wacom_wac->touch_input->name = wacom_wac->touch_name; ··· 1794 1448 } else { 1795 1449 error = input_register_device(pen_input_dev); 1796 1450 if (error) 1797 - goto fail_register_pen_input; 1798 - wacom_wac->pen_registered = true; 1451 + goto fail; 1799 1452 } 1800 1453 1801 1454 error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac); ··· 1806 1461 } else { 1807 1462 error = input_register_device(touch_input_dev); 1808 1463 if (error) 1809 - goto fail_register_touch_input; 1810 - wacom_wac->touch_registered = true; 1464 + goto fail; 1811 1465 } 1812 1466 1813 1467 error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); ··· 1818 1474 } else { 1819 1475 error = input_register_device(pad_input_dev); 1820 1476 if (error) 1821 - goto fail_register_pad_input; 1822 - wacom_wac->pad_registered = true; 1823 - 1824 - error = wacom_initialize_leds(wacom); 1825 - if (error) 1826 - goto fail_leds; 1827 - 1828 - error = wacom_initialize_remote(wacom); 1829 - if (error) 1830 - goto fail_remote; 1477 + goto fail; 1831 1478 } 1832 1479 1833 1480 return 0; 1834 1481 1835 - fail_remote: 1836 - wacom_destroy_leds(wacom); 1837 - fail_leds: 1838 - input_unregister_device(pad_input_dev); 1839 - pad_input_dev = NULL; 1840 - wacom_wac->pad_registered = false; 1841 - fail_register_pad_input: 1842 - if (touch_input_dev) 1843 - input_unregister_device(touch_input_dev); 1482 + fail: 1483 + wacom_wac->pad_input = NULL; 1844 1484 wacom_wac->touch_input = NULL; 1845 - wacom_wac->touch_registered = false; 1846 - fail_register_touch_input: 1847 - if (pen_input_dev) 1848 - input_unregister_device(pen_input_dev); 1849 1485 wacom_wac->pen_input = NULL; 1850 - wacom_wac->pen_registered = false; 1851 - fail_register_pen_input: 1852 1486 return error; 1853 1487 } 1854 1488 ··· 1865 1543 1866 1544 void wacom_battery_work(struct work_struct *work) 1867 1545 { 1868 - struct wacom *wacom = container_of(work, struct wacom, work); 1546 + struct wacom *wacom = container_of(work, struct wacom, battery_work); 1869 1547 1870 1548 if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && 1871 - !wacom->battery) { 1549 + !wacom->battery.battery) { 1872 1550 wacom_initialize_battery(wacom); 1873 1551 } 1874 1552 else if (!(wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) && 1875 - wacom->battery) { 1553 + wacom->battery.battery) { 1876 1554 wacom_destroy_battery(wacom); 1877 1555 } 1878 1556 } ··· 1928 1606 strlcpy(name, features->name, sizeof(name)); 1929 1607 } 1930 1608 1609 + snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s", 1610 + name, suffix); 1611 + 1931 1612 /* Append the device type to the name */ 1932 1613 snprintf(wacom_wac->pen_name, sizeof(wacom_wac->pen_name), 1933 1614 "%s%s Pen", name, suffix); ··· 1938 1613 "%s%s Finger", name, suffix); 1939 1614 snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), 1940 1615 "%s%s Pad", name, suffix); 1616 + } 1617 + 1618 + static void wacom_release_resources(struct wacom *wacom) 1619 + { 1620 + struct hid_device *hdev = wacom->hdev; 1621 + 1622 + if (!wacom->resources) 1623 + return; 1624 + 1625 + devres_release_group(&hdev->dev, wacom); 1626 + 1627 + wacom->resources = false; 1628 + 1629 + wacom->wacom_wac.pen_input = NULL; 1630 + wacom->wacom_wac.touch_input = NULL; 1631 + wacom->wacom_wac.pad_input = NULL; 1941 1632 } 1942 1633 1943 1634 static int wacom_parse_and_register(struct wacom *wacom, bool wireless) ··· 1968 1627 if (features->pktlen > WACOM_PKGLEN_MAX) 1969 1628 return -EINVAL; 1970 1629 1630 + if (!devres_open_group(&hdev->dev, wacom, GFP_KERNEL)) 1631 + return -ENOMEM; 1632 + 1633 + wacom->resources = true; 1634 + 1971 1635 error = wacom_allocate_inputs(wacom); 1972 1636 if (error) 1973 - return error; 1637 + goto fail; 1974 1638 1975 1639 /* 1976 1640 * Bamboo Pad has a generic hid handling for the Pen, and we switch it ··· 1988 1642 } else if ((features->pktlen != WACOM_PKGLEN_BPAD_TOUCH) && 1989 1643 (features->pktlen != WACOM_PKGLEN_BPAD_TOUCH_USB)) { 1990 1644 error = -ENODEV; 1991 - goto fail_allocate_inputs; 1645 + goto fail; 1992 1646 } 1993 1647 } 1994 1648 ··· 2008 1662 error ? "Ignoring" : "Assuming pen"); 2009 1663 2010 1664 if (error) 2011 - goto fail_parsed; 1665 + goto fail; 2012 1666 2013 1667 features->device_type |= WACOM_DEVICETYPE_PEN; 2014 1668 } ··· 2019 1673 2020 1674 error = wacom_add_shared_data(hdev); 2021 1675 if (error) 2022 - goto fail_shared_data; 1676 + goto fail; 2023 1677 2024 1678 if (!(features->device_type & WACOM_DEVICETYPE_WL_MONITOR) && 2025 1679 (features->quirks & WACOM_QUIRK_BATTERY)) { 2026 1680 error = wacom_initialize_battery(wacom); 2027 1681 if (error) 2028 - goto fail_battery; 1682 + goto fail; 2029 1683 } 2030 1684 2031 1685 error = wacom_register_inputs(wacom); 2032 1686 if (error) 2033 - goto fail_register_inputs; 1687 + goto fail; 1688 + 1689 + if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PAD) { 1690 + error = wacom_initialize_leds(wacom); 1691 + if (error) 1692 + goto fail; 1693 + 1694 + error = wacom_initialize_remotes(wacom); 1695 + if (error) 1696 + goto fail; 1697 + } 2034 1698 2035 1699 if (features->type == HID_GENERIC) 2036 1700 connect_mask |= HID_CONNECT_DRIVER; ··· 2049 1693 error = hid_hw_start(hdev, connect_mask); 2050 1694 if (error) { 2051 1695 hid_err(hdev, "hw start failed\n"); 2052 - goto fail_hw_start; 1696 + goto fail; 2053 1697 } 2054 1698 2055 1699 if (!wireless) { ··· 2061 1705 if ((features->type == BAMBOO_TOUCH) && 2062 1706 (features->device_type & WACOM_DEVICETYPE_PEN)) { 2063 1707 error = -ENODEV; 2064 - goto fail_hw_start; 1708 + goto fail_quirks; 2065 1709 } 2066 1710 2067 1711 /* pen only Bamboo neither support touch nor pad */ ··· 2069 1713 ((features->device_type & WACOM_DEVICETYPE_TOUCH) || 2070 1714 (features->device_type & WACOM_DEVICETYPE_PAD))) { 2071 1715 error = -ENODEV; 2072 - goto fail_hw_start; 1716 + goto fail_quirks; 2073 1717 } 2074 1718 2075 1719 if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) 2076 1720 error = hid_hw_open(hdev); 2077 1721 2078 1722 if ((wacom_wac->features.type == INTUOSHT || 2079 - wacom_wac->features.type == INTUOSHT2) && 1723 + wacom_wac->features.type == INTUOSHT2) && 2080 1724 (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH)) { 2081 - wacom_wac->shared->touch_input = wacom_wac->touch_input; 1725 + wacom_wac->shared->type = wacom_wac->features.type; 1726 + wacom_wac->shared->touch_input = wacom_wac->touch_input; 2082 1727 } 1728 + 1729 + devres_close_group(&hdev->dev, wacom); 2083 1730 2084 1731 return 0; 2085 1732 2086 - fail_hw_start: 1733 + fail_quirks: 2087 1734 hid_hw_stop(hdev); 2088 - fail_register_inputs: 2089 - wacom_clean_inputs(wacom); 2090 - wacom_destroy_battery(wacom); 2091 - fail_battery: 2092 - wacom_remove_shared_data(wacom); 2093 - fail_shared_data: 2094 - fail_parsed: 2095 - fail_allocate_inputs: 2096 - wacom_clean_inputs(wacom); 1735 + fail: 1736 + wacom_release_resources(wacom); 2097 1737 return error; 2098 1738 } 2099 1739 2100 1740 static void wacom_wireless_work(struct work_struct *work) 2101 1741 { 2102 - struct wacom *wacom = container_of(work, struct wacom, work); 1742 + struct wacom *wacom = container_of(work, struct wacom, wireless_work); 2103 1743 struct usb_device *usbdev = wacom->usbdev; 2104 1744 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 2105 1745 struct hid_device *hdev1, *hdev2; ··· 2114 1762 hdev1 = usb_get_intfdata(usbdev->config->interface[1]); 2115 1763 wacom1 = hid_get_drvdata(hdev1); 2116 1764 wacom_wac1 = &(wacom1->wacom_wac); 2117 - wacom_clean_inputs(wacom1); 1765 + wacom_release_resources(wacom1); 2118 1766 2119 1767 /* Touch interface */ 2120 1768 hdev2 = usb_get_intfdata(usbdev->config->interface[2]); 2121 1769 wacom2 = hid_get_drvdata(hdev2); 2122 1770 wacom_wac2 = &(wacom2->wacom_wac); 2123 - wacom_clean_inputs(wacom2); 1771 + wacom_release_resources(wacom2); 2124 1772 2125 1773 if (wacom_wac->pid == 0) { 2126 1774 hid_info(wacom->hdev, "wireless tablet disconnected\n"); 2127 - wacom_wac1->shared->type = 0; 2128 1775 } else { 2129 1776 const struct hid_device_id *id = wacom_ids; 2130 1777 ··· 2165 1814 goto fail; 2166 1815 } 2167 1816 1817 + strlcpy(wacom_wac->name, wacom_wac1->name, 1818 + sizeof(wacom_wac->name)); 2168 1819 error = wacom_initialize_battery(wacom); 2169 1820 if (error) 2170 1821 goto fail; ··· 2175 1822 return; 2176 1823 2177 1824 fail: 2178 - wacom_clean_inputs(wacom1); 2179 - wacom_clean_inputs(wacom2); 1825 + wacom_release_resources(wacom1); 1826 + wacom_release_resources(wacom2); 2180 1827 return; 1828 + } 1829 + 1830 + static void wacom_remote_destroy_one(struct wacom *wacom, unsigned int index) 1831 + { 1832 + struct wacom_remote *remote = wacom->remote; 1833 + u32 serial = remote->remotes[index].serial; 1834 + int i; 1835 + unsigned long flags; 1836 + 1837 + spin_lock_irqsave(&remote->remote_lock, flags); 1838 + remote->remotes[index].registered = false; 1839 + spin_unlock_irqrestore(&remote->remote_lock, flags); 1840 + 1841 + if (remote->remotes[index].battery.battery) 1842 + devres_release_group(&wacom->hdev->dev, 1843 + &remote->remotes[index].battery.bat_desc); 1844 + 1845 + if (remote->remotes[index].group.name) 1846 + devres_release_group(&wacom->hdev->dev, 1847 + &remote->remotes[index]); 1848 + 1849 + for (i = 0; i < WACOM_MAX_REMOTES; i++) { 1850 + if (remote->remotes[i].serial == serial) { 1851 + remote->remotes[i].serial = 0; 1852 + remote->remotes[i].group.name = NULL; 1853 + remote->remotes[i].registered = false; 1854 + remote->remotes[i].battery.battery = NULL; 1855 + wacom->led.groups[i].select = WACOM_STATUS_UNKNOWN; 1856 + } 1857 + } 1858 + } 1859 + 1860 + static int wacom_remote_create_one(struct wacom *wacom, u32 serial, 1861 + unsigned int index) 1862 + { 1863 + struct wacom_remote *remote = wacom->remote; 1864 + struct device *dev = &wacom->hdev->dev; 1865 + int error, k; 1866 + 1867 + /* A remote can pair more than once with an EKR, 1868 + * check to make sure this serial isn't already paired. 1869 + */ 1870 + for (k = 0; k < WACOM_MAX_REMOTES; k++) { 1871 + if (remote->remotes[k].serial == serial) 1872 + break; 1873 + } 1874 + 1875 + if (k < WACOM_MAX_REMOTES) { 1876 + remote->remotes[index].serial = serial; 1877 + return 0; 1878 + } 1879 + 1880 + if (!devres_open_group(dev, &remote->remotes[index], GFP_KERNEL)) 1881 + return -ENOMEM; 1882 + 1883 + error = wacom_remote_create_attr_group(wacom, serial, index); 1884 + if (error) 1885 + goto fail; 1886 + 1887 + remote->remotes[index].input = wacom_allocate_input(wacom); 1888 + if (!remote->remotes[index].input) { 1889 + error = -ENOMEM; 1890 + goto fail; 1891 + } 1892 + remote->remotes[index].input->uniq = remote->remotes[index].group.name; 1893 + remote->remotes[index].input->name = wacom->wacom_wac.pad_name; 1894 + 1895 + if (!remote->remotes[index].input->name) { 1896 + error = -EINVAL; 1897 + goto fail; 1898 + } 1899 + 1900 + error = wacom_setup_pad_input_capabilities(remote->remotes[index].input, 1901 + &wacom->wacom_wac); 1902 + if (error) 1903 + goto fail; 1904 + 1905 + remote->remotes[index].serial = serial; 1906 + 1907 + error = input_register_device(remote->remotes[index].input); 1908 + if (error) 1909 + goto fail; 1910 + 1911 + error = wacom_led_groups_alloc_and_register_one( 1912 + &remote->remotes[index].input->dev, 1913 + wacom, index, 3, true); 1914 + if (error) 1915 + goto fail; 1916 + 1917 + remote->remotes[index].registered = true; 1918 + 1919 + devres_close_group(dev, &remote->remotes[index]); 1920 + return 0; 1921 + 1922 + fail: 1923 + devres_release_group(dev, &remote->remotes[index]); 1924 + remote->remotes[index].serial = 0; 1925 + return error; 1926 + } 1927 + 1928 + static int wacom_remote_attach_battery(struct wacom *wacom, int index) 1929 + { 1930 + struct wacom_remote *remote = wacom->remote; 1931 + int error; 1932 + 1933 + if (!remote->remotes[index].registered) 1934 + return 0; 1935 + 1936 + if (remote->remotes[index].battery.battery) 1937 + return 0; 1938 + 1939 + if (wacom->led.groups[index].select == WACOM_STATUS_UNKNOWN) 1940 + return 0; 1941 + 1942 + error = __wacom_initialize_battery(wacom, 1943 + &wacom->remote->remotes[index].battery); 1944 + if (error) 1945 + return error; 1946 + 1947 + return 0; 1948 + } 1949 + 1950 + static void wacom_remote_work(struct work_struct *work) 1951 + { 1952 + struct wacom *wacom = container_of(work, struct wacom, remote_work); 1953 + struct wacom_remote *remote = wacom->remote; 1954 + struct wacom_remote_data data; 1955 + unsigned long flags; 1956 + unsigned int count; 1957 + u32 serial; 1958 + int i; 1959 + 1960 + spin_lock_irqsave(&remote->remote_lock, flags); 1961 + 1962 + count = kfifo_out(&remote->remote_fifo, &data, sizeof(data)); 1963 + 1964 + if (count != sizeof(data)) { 1965 + hid_err(wacom->hdev, 1966 + "workitem triggered without status available\n"); 1967 + spin_unlock_irqrestore(&remote->remote_lock, flags); 1968 + return; 1969 + } 1970 + 1971 + if (!kfifo_is_empty(&remote->remote_fifo)) 1972 + wacom_schedule_work(&wacom->wacom_wac, WACOM_WORKER_REMOTE); 1973 + 1974 + spin_unlock_irqrestore(&remote->remote_lock, flags); 1975 + 1976 + for (i = 0; i < WACOM_MAX_REMOTES; i++) { 1977 + serial = data.remote[i].serial; 1978 + if (data.remote[i].connected) { 1979 + 1980 + if (remote->remotes[i].serial == serial) { 1981 + wacom_remote_attach_battery(wacom, i); 1982 + continue; 1983 + } 1984 + 1985 + if (remote->remotes[i].serial) 1986 + wacom_remote_destroy_one(wacom, i); 1987 + 1988 + wacom_remote_create_one(wacom, serial, i); 1989 + 1990 + } else if (remote->remotes[i].serial) { 1991 + wacom_remote_destroy_one(wacom, i); 1992 + } 1993 + } 2181 1994 } 2182 1995 2183 1996 static int wacom_probe(struct hid_device *hdev, ··· 2364 1845 /* hid-core sets this quirk for the boot interface */ 2365 1846 hdev->quirks &= ~HID_QUIRK_NOGET; 2366 1847 2367 - wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); 1848 + wacom = devm_kzalloc(&hdev->dev, sizeof(struct wacom), GFP_KERNEL); 2368 1849 if (!wacom) 2369 1850 return -ENOMEM; 2370 1851 ··· 2377 1858 2378 1859 if (features->check_for_hid_type && features->hid_type != hdev->type) { 2379 1860 error = -ENODEV; 2380 - goto fail_type; 1861 + goto fail; 2381 1862 } 2382 1863 2383 1864 wacom_wac->hid_data.inputmode = -1; ··· 2386 1867 wacom->usbdev = dev; 2387 1868 wacom->intf = intf; 2388 1869 mutex_init(&wacom->lock); 2389 - INIT_WORK(&wacom->work, wacom_wireless_work); 1870 + INIT_WORK(&wacom->wireless_work, wacom_wireless_work); 1871 + INIT_WORK(&wacom->battery_work, wacom_battery_work); 1872 + INIT_WORK(&wacom->remote_work, wacom_remote_work); 2390 1873 2391 1874 /* ask for the report descriptor to be loaded by HID */ 2392 1875 error = hid_parse(hdev); 2393 1876 if (error) { 2394 1877 hid_err(hdev, "parse failed\n"); 2395 - goto fail_parse; 1878 + goto fail; 2396 1879 } 2397 1880 2398 1881 error = wacom_parse_and_register(wacom, false); 2399 1882 if (error) 2400 - goto fail_parse; 1883 + goto fail; 2401 1884 2402 1885 if (hdev->bus == BUS_BLUETOOTH) { 2403 1886 error = device_create_file(&hdev->dev, &dev_attr_speed); ··· 2411 1890 2412 1891 return 0; 2413 1892 2414 - fail_type: 2415 - fail_parse: 2416 - kfree(wacom); 1893 + fail: 2417 1894 hid_set_drvdata(hdev, NULL); 2418 1895 return error; 2419 1896 } ··· 2427 1908 2428 1909 hid_hw_stop(hdev); 2429 1910 2430 - cancel_work_sync(&wacom->work); 2431 - wacom_clean_inputs(wacom); 1911 + cancel_work_sync(&wacom->wireless_work); 1912 + cancel_work_sync(&wacom->battery_work); 1913 + cancel_work_sync(&wacom->remote_work); 2432 1914 if (hdev->bus == BUS_BLUETOOTH) 2433 1915 device_remove_file(&hdev->dev, &dev_attr_speed); 2434 - wacom_destroy_battery(wacom); 2435 - wacom_remove_shared_data(wacom); 2436 1916 2437 1917 hid_set_drvdata(hdev, NULL); 2438 - kfree(wacom); 2439 1918 } 2440 1919 2441 1920 #ifdef CONFIG_PM
+283 -156
drivers/hid/wacom_wac.c
··· 34 34 */ 35 35 #define WACOM_CONTACT_AREA_SCALE 2607 36 36 37 + static bool touch_arbitration = 1; 38 + module_param(touch_arbitration, bool, 0644); 39 + MODULE_PARM_DESC(touch_arbitration, " on (Y) off (N)"); 40 + 37 41 static void wacom_report_numbered_buttons(struct input_dev *input_dev, 38 42 int button_count, int mask); 39 43 ··· 52 48 */ 53 49 static unsigned short batcap_i4[8] = { 1, 15, 30, 45, 60, 70, 85, 100 }; 54 50 51 + static void __wacom_notify_battery(struct wacom_battery *battery, 52 + int bat_capacity, bool bat_charging, 53 + bool bat_connected, bool ps_connected) 54 + { 55 + bool changed = battery->battery_capacity != bat_capacity || 56 + battery->bat_charging != bat_charging || 57 + battery->bat_connected != bat_connected || 58 + battery->ps_connected != ps_connected; 59 + 60 + if (changed) { 61 + battery->battery_capacity = bat_capacity; 62 + battery->bat_charging = bat_charging; 63 + battery->bat_connected = bat_connected; 64 + battery->ps_connected = ps_connected; 65 + 66 + if (battery->battery) 67 + power_supply_changed(battery->battery); 68 + } 69 + } 70 + 55 71 static void wacom_notify_battery(struct wacom_wac *wacom_wac, 56 72 int bat_capacity, bool bat_charging, bool bat_connected, 57 73 bool ps_connected) 58 74 { 59 75 struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); 60 - bool changed = wacom_wac->battery_capacity != bat_capacity || 61 - wacom_wac->bat_charging != bat_charging || 62 - wacom_wac->bat_connected != bat_connected || 63 - wacom_wac->ps_connected != ps_connected; 64 76 65 - if (changed) { 66 - wacom_wac->battery_capacity = bat_capacity; 67 - wacom_wac->bat_charging = bat_charging; 68 - wacom_wac->bat_connected = bat_connected; 69 - wacom_wac->ps_connected = ps_connected; 70 - 71 - if (wacom->battery) 72 - power_supply_changed(wacom->battery); 73 - } 77 + __wacom_notify_battery(&wacom->battery, bat_capacity, bat_charging, 78 + bat_connected, ps_connected); 74 79 } 75 80 76 81 static int wacom_penpartner_irq(struct wacom_wac *wacom) ··· 764 751 static int wacom_remote_irq(struct wacom_wac *wacom_wac, size_t len) 765 752 { 766 753 unsigned char *data = wacom_wac->data; 767 - struct input_dev *input = wacom_wac->pad_input; 754 + struct input_dev *input; 768 755 struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); 769 - struct wacom_features *features = &wacom_wac->features; 756 + struct wacom_remote *remote = wacom->remote; 770 757 int bat_charging, bat_percent, touch_ring_mode; 771 758 __u32 serial; 772 - int i; 759 + int i, index = -1; 760 + unsigned long flags; 773 761 774 762 if (data[0] != WACOM_REPORT_REMOTE) { 775 - dev_dbg(input->dev.parent, 776 - "%s: received unknown report #%d", __func__, data[0]); 763 + hid_dbg(wacom->hdev, "%s: received unknown report #%d", 764 + __func__, data[0]); 777 765 return 0; 778 766 } 779 767 780 768 serial = data[3] + (data[4] << 8) + (data[5] << 16); 781 769 wacom_wac->id[0] = PAD_DEVICE_ID; 770 + 771 + spin_lock_irqsave(&remote->remote_lock, flags); 772 + 773 + for (i = 0; i < WACOM_MAX_REMOTES; i++) { 774 + if (remote->remotes[i].serial == serial) { 775 + index = i; 776 + break; 777 + } 778 + } 779 + 780 + if (index < 0 || !remote->remotes[index].registered) 781 + goto out; 782 + 783 + input = remote->remotes[index].input; 782 784 783 785 input_report_key(input, BTN_0, (data[9] & 0x01)); 784 786 input_report_key(input, BTN_1, (data[9] & 0x02)); ··· 831 803 832 804 input_event(input, EV_MSC, MSC_SERIAL, serial); 833 805 806 + input_sync(input); 807 + 834 808 /*Which mode select (LED light) is currently on?*/ 835 809 touch_ring_mode = (data[11] & 0xC0) >> 6; 836 810 837 811 for (i = 0; i < WACOM_MAX_REMOTES; i++) { 838 - if (wacom_wac->serial[i] == serial) 839 - wacom->led.select[i] = touch_ring_mode; 812 + if (remote->remotes[i].serial == serial) 813 + wacom->led.groups[i].select = touch_ring_mode; 840 814 } 841 815 842 - if (!wacom->battery && 843 - !(features->quirks & WACOM_QUIRK_BATTERY)) { 844 - features->quirks |= WACOM_QUIRK_BATTERY; 845 - INIT_WORK(&wacom->work, wacom_battery_work); 846 - wacom_schedule_work(wacom_wac); 847 - } 816 + __wacom_notify_battery(&remote->remotes[index].battery, bat_percent, 817 + bat_charging, 1, bat_charging); 848 818 849 - wacom_notify_battery(wacom_wac, bat_percent, bat_charging, 1, 850 - bat_charging); 851 - 852 - return 1; 819 + out: 820 + spin_unlock_irqrestore(&remote->remote_lock, flags); 821 + return 0; 853 822 } 854 823 855 - static int wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) 824 + static void wacom_remote_status_irq(struct wacom_wac *wacom_wac, size_t len) 856 825 { 857 826 struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac); 858 827 unsigned char *data = wacom_wac->data; 859 - int i; 828 + struct wacom_remote *remote = wacom->remote; 829 + struct wacom_remote_data remote_data; 830 + unsigned long flags; 831 + int i, ret; 860 832 861 833 if (data[0] != WACOM_REPORT_DEVICE_LIST) 862 - return 0; 834 + return; 835 + 836 + memset(&remote_data, 0, sizeof(struct wacom_remote_data)); 863 837 864 838 for (i = 0; i < WACOM_MAX_REMOTES; i++) { 865 839 int j = i * 6; 866 840 int serial = (data[j+6] << 16) + (data[j+5] << 8) + data[j+4]; 867 841 bool connected = data[j+2]; 868 842 869 - if (connected) { 870 - int k; 871 - 872 - if (wacom_wac->serial[i] == serial) 873 - continue; 874 - 875 - if (wacom_wac->serial[i]) { 876 - wacom_remote_destroy_attr_group(wacom, 877 - wacom_wac->serial[i]); 878 - } 879 - 880 - /* A remote can pair more than once with an EKR, 881 - * check to make sure this serial isn't already paired. 882 - */ 883 - for (k = 0; k < WACOM_MAX_REMOTES; k++) { 884 - if (wacom_wac->serial[k] == serial) 885 - break; 886 - } 887 - 888 - if (k < WACOM_MAX_REMOTES) { 889 - wacom_wac->serial[i] = serial; 890 - continue; 891 - } 892 - wacom_remote_create_attr_group(wacom, serial, i); 893 - 894 - } else if (wacom_wac->serial[i]) { 895 - wacom_remote_destroy_attr_group(wacom, 896 - wacom_wac->serial[i]); 897 - } 843 + remote_data.remote[i].serial = serial; 844 + remote_data.remote[i].connected = connected; 898 845 } 899 846 900 - return 0; 847 + spin_lock_irqsave(&remote->remote_lock, flags); 848 + 849 + ret = kfifo_in(&remote->remote_fifo, &remote_data, sizeof(remote_data)); 850 + if (ret != sizeof(remote_data)) { 851 + spin_unlock_irqrestore(&remote->remote_lock, flags); 852 + hid_err(wacom->hdev, "Can't queue Remote status event.\n"); 853 + return; 854 + } 855 + 856 + spin_unlock_irqrestore(&remote->remote_lock, flags); 857 + 858 + wacom_schedule_work(wacom_wac, WACOM_WORKER_REMOTE); 859 + } 860 + 861 + static inline bool report_touch_events(struct wacom_wac *wacom) 862 + { 863 + return (touch_arbitration ? !wacom->shared->stylus_in_proximity : 1); 864 + } 865 + 866 + static inline bool delay_pen_events(struct wacom_wac *wacom) 867 + { 868 + return (wacom->shared->touch_down && touch_arbitration); 901 869 } 902 870 903 871 static int wacom_intuos_general(struct wacom_wac *wacom) ··· 909 885 data[0] != WACOM_REPORT_INTUOS_PEN) 910 886 return 0; 911 887 912 - if (wacom->shared->touch_down) 888 + if (delay_pen_events(wacom)) 913 889 return 1; 914 890 915 891 /* don't report events if we don't know the tool ID */ ··· 1169 1145 1170 1146 if (touch_max == 1) 1171 1147 return test_bit(BTN_TOUCH, input->key) && 1172 - !wacom->shared->stylus_in_proximity; 1148 + report_touch_events(wacom); 1173 1149 1174 1150 for (i = 0; i < input->mt->num_slots; i++) { 1175 1151 struct input_mt_slot *ps = &input->mt->slots[i]; ··· 1210 1186 1211 1187 for (i = 0; i < contacts_to_send; i++) { 1212 1188 int offset = (byte_per_packet * i) + 1; 1213 - bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity; 1189 + bool touch = (data[offset] & 0x1) && report_touch_events(wacom); 1214 1190 int slot = input_mt_get_slot_by_key(input, data[offset + 1]); 1215 1191 1216 1192 if (slot < 0) ··· 1274 1250 1275 1251 for (i = 0; i < contacts_to_send; i++) { 1276 1252 int offset = (WACOM_BYTES_PER_MT_PACKET + x_offset) * i + 3; 1277 - bool touch = (data[offset] & 0x1) && !wacom->shared->stylus_in_proximity; 1253 + bool touch = (data[offset] & 0x1) && report_touch_events(wacom); 1278 1254 int id = get_unaligned_le16(&data[offset + 1]); 1279 1255 int slot = input_mt_get_slot_by_key(input, id); 1280 1256 ··· 1308 1284 1309 1285 for (i = 0; i < 2; i++) { 1310 1286 int p = data[1] & (1 << i); 1311 - bool touch = p && !wacom->shared->stylus_in_proximity; 1287 + bool touch = p && report_touch_events(wacom); 1312 1288 1313 1289 input_mt_slot(input, i); 1314 1290 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); ··· 1332 1308 { 1333 1309 unsigned char *data = wacom->data; 1334 1310 struct input_dev *input = wacom->touch_input; 1335 - bool prox = !wacom->shared->stylus_in_proximity; 1311 + bool prox = report_touch_events(wacom); 1336 1312 int x = 0, y = 0; 1337 1313 1338 1314 if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) ··· 1377 1353 /* keep pen state for touch events */ 1378 1354 wacom->shared->stylus_in_proximity = prox; 1379 1355 1380 - /* send pen events only when touch is up or forced out */ 1381 - if (!wacom->shared->touch_down) { 1356 + /* send pen events only when touch is up or forced out 1357 + * or touch arbitration is off 1358 + */ 1359 + if (!delay_pen_events(wacom)) { 1382 1360 input_report_key(input, BTN_STYLUS, data[1] & 0x02); 1383 1361 input_report_key(input, BTN_STYLUS2, data[1] & 0x10); 1384 1362 input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); ··· 1522 1496 return 0; 1523 1497 } 1524 1498 1525 - /* send pen events only when touch is up or forced out */ 1526 - if (!usage->type || wacom_wac->shared->touch_down) 1499 + /* send pen events only when touch is up or forced out 1500 + * or touch arbitration is off 1501 + */ 1502 + if (!usage->type || delay_pen_events(wacom_wac)) 1527 1503 return 0; 1528 1504 1529 1505 input_event(input, usage->type, usage->code, value); ··· 1555 1527 /* keep pen state for touch events */ 1556 1528 wacom_wac->shared->stylus_in_proximity = prox; 1557 1529 1558 - /* send pen events only when touch is up or forced out */ 1559 - if (!wacom_wac->shared->touch_down) { 1530 + if (!delay_pen_events(wacom_wac)) { 1560 1531 input_report_key(input, BTN_TOUCH, 1561 1532 wacom_wac->hid_data.tipswitch); 1562 1533 input_report_key(input, wacom_wac->tool[0], prox); ··· 1571 1544 { 1572 1545 struct wacom *wacom = hid_get_drvdata(hdev); 1573 1546 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1574 - struct wacom_features *features = &wacom_wac->features; 1575 1547 struct input_dev *input = wacom_wac->touch_input; 1576 1548 unsigned touch_max = wacom_wac->features.touch_max; 1577 1549 1578 1550 switch (usage->hid) { 1579 1551 case HID_GD_X: 1580 - features->last_slot_field = usage->hid; 1581 1552 if (touch_max == 1) 1582 1553 wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); 1583 1554 else ··· 1583 1558 ABS_MT_POSITION_X, 4); 1584 1559 break; 1585 1560 case HID_GD_Y: 1586 - features->last_slot_field = usage->hid; 1587 1561 if (touch_max == 1) 1588 1562 wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); 1589 1563 else ··· 1591 1567 break; 1592 1568 case HID_DG_WIDTH: 1593 1569 case HID_DG_HEIGHT: 1594 - features->last_slot_field = usage->hid; 1595 1570 wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MAJOR, 0); 1596 1571 wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_TOUCH_MINOR, 0); 1597 1572 input_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); 1598 1573 break; 1599 - case HID_DG_CONTACTID: 1600 - features->last_slot_field = usage->hid; 1601 - break; 1602 - case HID_DG_INRANGE: 1603 - features->last_slot_field = usage->hid; 1604 - break; 1605 - case HID_DG_INVERT: 1606 - features->last_slot_field = usage->hid; 1607 - break; 1608 1574 case HID_DG_TIPSWITCH: 1609 - features->last_slot_field = usage->hid; 1610 1575 wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); 1611 1576 break; 1612 1577 case HID_DG_CONTACTCOUNT: ··· 1612 1599 struct hid_data *hid_data = &wacom_wac->hid_data; 1613 1600 bool mt = wacom_wac->features.touch_max > 1; 1614 1601 bool prox = hid_data->tipswitch && 1615 - !wacom_wac->shared->stylus_in_proximity; 1602 + report_touch_events(wacom_wac); 1616 1603 1617 1604 wacom_wac->hid_data.num_received++; 1618 1605 if (wacom_wac->hid_data.num_received > wacom_wac->hid_data.num_expected) ··· 1673 1660 1674 1661 1675 1662 if (usage->usage_index + 1 == field->report_count) { 1676 - if (usage->hid == wacom_wac->features.last_slot_field) 1663 + if (usage->hid == wacom_wac->hid_data.last_slot_field) 1677 1664 wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); 1678 1665 } 1679 1666 ··· 1686 1673 struct wacom *wacom = hid_get_drvdata(hdev); 1687 1674 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1688 1675 struct hid_data* hid_data = &wacom_wac->hid_data; 1676 + int i; 1689 1677 1690 - if (hid_data->cc_report != 0 && 1691 - hid_data->cc_report != report->id) { 1692 - int i; 1678 + for (i = 0; i < report->maxfield; i++) { 1679 + struct hid_field *field = report->field[i]; 1680 + int j; 1693 1681 1694 - hid_data->cc_report = report->id; 1695 - hid_data->cc_index = -1; 1696 - hid_data->cc_value_index = -1; 1682 + for (j = 0; j < field->maxusage; j++) { 1683 + struct hid_usage *usage = &field->usage[j]; 1697 1684 1698 - for (i = 0; i < report->maxfield; i++) { 1699 - struct hid_field *field = report->field[i]; 1700 - int j; 1701 - 1702 - for (j = 0; j < field->maxusage; j++) { 1703 - if (field->usage[j].hid == HID_DG_CONTACTCOUNT) { 1704 - hid_data->cc_index = i; 1705 - hid_data->cc_value_index = j; 1706 - 1707 - /* break */ 1708 - i = report->maxfield; 1709 - j = field->maxusage; 1710 - } 1685 + switch (usage->hid) { 1686 + case HID_GD_X: 1687 + case HID_GD_Y: 1688 + case HID_DG_WIDTH: 1689 + case HID_DG_HEIGHT: 1690 + case HID_DG_CONTACTID: 1691 + case HID_DG_INRANGE: 1692 + case HID_DG_INVERT: 1693 + case HID_DG_TIPSWITCH: 1694 + hid_data->last_slot_field = usage->hid; 1695 + break; 1696 + case HID_DG_CONTACTCOUNT: 1697 + hid_data->cc_report = report->id; 1698 + hid_data->cc_index = i; 1699 + hid_data->cc_value_index = j; 1700 + break; 1711 1701 } 1712 1702 } 1713 1703 } 1704 + 1714 1705 if (hid_data->cc_report != 0 && 1715 1706 hid_data->cc_index >= 0) { 1716 1707 struct hid_field *field = report->field[hid_data->cc_index]; ··· 1757 1740 { 1758 1741 struct wacom *wacom = hid_get_drvdata(hdev); 1759 1742 struct wacom_wac *wacom_wac = &wacom->wacom_wac; 1743 + struct wacom_features *features = &wacom_wac->features; 1760 1744 1761 1745 /* currently, only direct devices have proper hid report descriptors */ 1762 - __set_bit(INPUT_PROP_DIRECT, wacom_wac->pen_input->propbit); 1763 - __set_bit(INPUT_PROP_DIRECT, wacom_wac->touch_input->propbit); 1746 + features->device_type |= WACOM_DEVICETYPE_DIRECT; 1764 1747 1765 1748 if (WACOM_PEN_FIELD(field)) 1766 1749 return wacom_wac_pen_usage_mapping(hdev, field, usage); ··· 1842 1825 1843 1826 for (i = 0; i < 2; i++) { 1844 1827 int offset = (data[1] & 0x80) ? (8 * i) : (9 * i); 1845 - bool touch = data[offset + 3] & 0x80; 1846 - 1847 - /* 1848 - * Touch events need to be disabled while stylus is 1849 - * in proximity because user's hand is resting on touchpad 1850 - * and sending unwanted events. User expects tablet buttons 1851 - * to continue working though. 1852 - */ 1853 - touch = touch && !wacom->shared->stylus_in_proximity; 1828 + bool touch = report_touch_events(wacom) 1829 + && (data[offset + 3] & 0x80); 1854 1830 1855 1831 input_mt_slot(input, i); 1856 1832 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); ··· 1880 1870 if (slot < 0) 1881 1871 return; 1882 1872 1883 - touch = touch && !wacom->shared->stylus_in_proximity; 1873 + touch = touch && report_touch_events(wacom); 1884 1874 1885 1875 input_mt_slot(input, slot); 1886 1876 input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); ··· 1952 1942 } 1953 1943 1954 1944 /* only update touch if we actually have a touchpad and touch data changed */ 1955 - if (wacom->touch_registered && touch_changed) { 1945 + if (wacom->touch_input && touch_changed) { 1956 1946 input_mt_sync_frame(wacom->touch_input); 1957 1947 wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); 1958 1948 } ··· 1993 1983 } 1994 1984 1995 1985 wacom->shared->stylus_in_proximity = prox; 1996 - if (wacom->shared->touch_down) 1986 + if (delay_pen_events(wacom)) 1997 1987 return 0; 1998 1988 1999 1989 if (prox) { ··· 2087 2077 2088 2078 for (id = 0; id < wacom->features.touch_max; id++) { 2089 2079 valid = !!(prefix & BIT(id)) && 2090 - !wacom->shared->stylus_in_proximity; 2080 + report_touch_events(wacom); 2091 2081 2092 2082 input_mt_slot(input, id); 2093 2083 input_mt_report_slot_state(input, MT_TOOL_FINGER, valid); ··· 2109 2099 input_report_key(input, BTN_RIGHT, prefix & 0x80); 2110 2100 2111 2101 /* keep touch state for pen event */ 2112 - wacom->shared->touch_down = !!prefix && 2113 - !wacom->shared->stylus_in_proximity; 2102 + wacom->shared->touch_down = !!prefix && report_touch_events(wacom); 2114 2103 2115 2104 return 1; 2116 2105 } ··· 2158 2149 charging = !!(data[5] & 0x80); 2159 2150 if (wacom->pid != pid) { 2160 2151 wacom->pid = pid; 2161 - wacom_schedule_work(wacom); 2152 + wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS); 2162 2153 } 2163 2154 2164 - if (wacom->shared->type) 2165 - wacom_notify_battery(wacom, battery, charging, 1, 0); 2155 + wacom_notify_battery(wacom, battery, charging, 1, 0); 2166 2156 2167 2157 } else if (wacom->pid != 0) { 2168 2158 /* disconnected while previously connected */ 2169 2159 wacom->pid = 0; 2170 - wacom_schedule_work(wacom); 2160 + wacom_schedule_work(wacom, WACOM_WORKER_WIRELESS); 2171 2161 wacom_notify_battery(wacom, 0, 0, 0, 0); 2172 2162 } 2173 2163 ··· 2198 2190 wacom_notify_battery(wacom_wac, battery, charging, 2199 2191 battery || charging, 1); 2200 2192 2201 - if (!wacom->battery && 2193 + if (!wacom->battery.battery && 2202 2194 !(features->quirks & WACOM_QUIRK_BATTERY)) { 2203 2195 features->quirks |= WACOM_QUIRK_BATTERY; 2204 - INIT_WORK(&wacom->work, wacom_battery_work); 2205 - wacom_schedule_work(wacom_wac); 2196 + wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); 2206 2197 } 2207 2198 } 2208 2199 else if ((features->quirks & WACOM_QUIRK_BATTERY) && 2209 - wacom->battery) { 2200 + wacom->battery.battery) { 2210 2201 features->quirks &= ~WACOM_QUIRK_BATTERY; 2211 - INIT_WORK(&wacom->work, wacom_battery_work); 2212 - wacom_schedule_work(wacom_wac); 2202 + wacom_schedule_work(wacom_wac, WACOM_WORKER_BATTERY); 2213 2203 wacom_notify_battery(wacom_wac, 0, 0, 0, 0); 2214 2204 } 2215 2205 return 0; ··· 2318 2312 break; 2319 2313 2320 2314 case REMOTE: 2315 + sync = false; 2321 2316 if (wacom_wac->data[0] == WACOM_REPORT_DEVICE_LIST) 2322 - sync = wacom_remote_status_irq(wacom_wac, len); 2317 + wacom_remote_status_irq(wacom_wac, len); 2323 2318 else 2324 2319 sync = wacom_remote_irq(wacom_wac, len); 2325 2320 break; ··· 2458 2451 if (features->type == REMOTE) 2459 2452 features->device_type = WACOM_DEVICETYPE_PAD; 2460 2453 2454 + switch (features->type) { 2455 + case PL: 2456 + case DTU: 2457 + case DTUS: 2458 + case DTUSX: 2459 + case WACOM_21UX2: 2460 + case WACOM_22HD: 2461 + case DTK: 2462 + case WACOM_24HD: 2463 + case WACOM_27QHD: 2464 + case CINTIQ_HYBRID: 2465 + case CINTIQ_COMPANION_2: 2466 + case CINTIQ: 2467 + case WACOM_BEE: 2468 + case WACOM_13HD: 2469 + case WACOM_24HDT: 2470 + case WACOM_27QHDT: 2471 + case TABLETPC: 2472 + case TABLETPCE: 2473 + case TABLETPC2FG: 2474 + case MTSCREEN: 2475 + case MTTPC: 2476 + case MTTPC_B: 2477 + features->device_type |= WACOM_DEVICETYPE_DIRECT; 2478 + break; 2479 + } 2480 + 2461 2481 if (wacom->hdev->bus == BUS_BLUETOOTH) 2462 2482 features->quirks |= WACOM_QUIRK_BATTERY; 2463 2483 ··· 2503 2469 features->quirks |= WACOM_QUIRK_BATTERY; 2504 2470 } 2505 2471 } 2472 + 2473 + if (features->type == REMOTE) 2474 + features->device_type |= WACOM_DEVICETYPE_WL_MONITOR; 2506 2475 } 2507 2476 2508 2477 int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, ··· 2517 2480 2518 2481 if (!(features->device_type & WACOM_DEVICETYPE_PEN)) 2519 2482 return -ENODEV; 2483 + 2484 + if (features->device_type & WACOM_DEVICETYPE_DIRECT) 2485 + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 2486 + else 2487 + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2520 2488 2521 2489 if (features->type == HID_GENERIC) 2522 2490 /* setup has already been done */ ··· 2540 2498 /* penabled devices have fixed resolution for each model */ 2541 2499 input_abs_set_res(input_dev, ABS_X, features->x_resolution); 2542 2500 input_abs_set_res(input_dev, ABS_Y, features->y_resolution); 2543 - 2544 2501 2545 2502 switch (features->type) { 2546 2503 case GRAPHIRE_BT: ··· 2564 2523 __set_bit(BTN_TOOL_MOUSE, input_dev->keybit); 2565 2524 __set_bit(BTN_STYLUS, input_dev->keybit); 2566 2525 __set_bit(BTN_STYLUS2, input_dev->keybit); 2567 - 2568 - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2569 2526 break; 2570 2527 2571 2528 case WACOM_27QHD: ··· 2578 2539 case CINTIQ_COMPANION_2: 2579 2540 input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); 2580 2541 input_abs_set_res(input_dev, ABS_Z, 287); 2581 - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 2582 2542 wacom_setup_cintiq(wacom_wac); 2583 2543 break; 2584 2544 ··· 2593 2555 /* fall through */ 2594 2556 2595 2557 case INTUOS: 2596 - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2597 - 2598 2558 wacom_setup_intuos(wacom_wac); 2599 2559 break; 2600 2560 ··· 2602 2566 case INTUOSPL: 2603 2567 case INTUOS5S: 2604 2568 case INTUOSPS: 2605 - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2606 - 2607 2569 input_set_abs_params(input_dev, ABS_DISTANCE, 0, 2608 2570 features->distance_max, 2609 2571 features->distance_fuzz, 0); ··· 2631 2597 __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); 2632 2598 __set_bit(BTN_STYLUS, input_dev->keybit); 2633 2599 __set_bit(BTN_STYLUS2, input_dev->keybit); 2634 - 2635 - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 2636 2600 break; 2637 2601 2638 2602 case PTU: ··· 2641 2609 __set_bit(BTN_TOOL_PEN, input_dev->keybit); 2642 2610 __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); 2643 2611 __set_bit(BTN_STYLUS, input_dev->keybit); 2644 - 2645 - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2646 2612 break; 2647 2613 2648 2614 case INTUOSHT: 2649 2615 case BAMBOO_PT: 2650 2616 case BAMBOO_PEN: 2651 2617 case INTUOSHT2: 2652 - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2653 - 2654 2618 if (features->type == INTUOSHT2) { 2655 2619 wacom_setup_basic_pro_pen(wacom_wac); 2656 2620 } else { ··· 2676 2648 2677 2649 if (!(features->device_type & WACOM_DEVICETYPE_TOUCH)) 2678 2650 return -ENODEV; 2651 + 2652 + if (features->device_type & WACOM_DEVICETYPE_DIRECT) 2653 + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 2654 + else 2655 + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2679 2656 2680 2657 if (features->type == HID_GENERIC) 2681 2658 /* setup has already been done */ ··· 2716 2683 case INTUOSPL: 2717 2684 case INTUOS5S: 2718 2685 case INTUOSPS: 2719 - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); 2720 - 2721 2686 input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); 2722 2687 input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); 2723 2688 input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); ··· 2738 2707 2739 2708 case TABLETPC: 2740 2709 case TABLETPCE: 2741 - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); 2742 2710 break; 2743 2711 2744 2712 case INTUOSHT: ··· 2782 2752 __set_bit(BTN_BASE + (i-16), input_dev->keybit); 2783 2753 } 2784 2754 2755 + static void wacom_24hd_update_leds(struct wacom *wacom, int mask, int group) 2756 + { 2757 + struct wacom_led *led; 2758 + int i; 2759 + bool updated = false; 2760 + 2761 + /* 2762 + * 24HD has LED group 1 to the left and LED group 0 to the right. 2763 + * So group 0 matches the second half of the buttons and thus the mask 2764 + * needs to be shifted. 2765 + */ 2766 + if (group == 0) 2767 + mask >>= 8; 2768 + 2769 + for (i = 0; i < 3; i++) { 2770 + led = wacom_led_find(wacom, group, i); 2771 + if (!led) { 2772 + hid_err(wacom->hdev, "can't find LED %d in group %d\n", 2773 + i, group); 2774 + continue; 2775 + } 2776 + if (!updated && mask & BIT(i)) { 2777 + led->held = true; 2778 + led_trigger_event(&led->trigger, LED_FULL); 2779 + } else { 2780 + led->held = false; 2781 + } 2782 + } 2783 + } 2784 + 2785 + static bool wacom_is_led_toggled(struct wacom *wacom, int button_count, 2786 + int mask, int group) 2787 + { 2788 + int button_per_group; 2789 + 2790 + /* 2791 + * 21UX2 has LED group 1 to the left and LED group 0 2792 + * to the right. We need to reverse the group to match this 2793 + * historical behavior. 2794 + */ 2795 + if (wacom->wacom_wac.features.type == WACOM_21UX2) 2796 + group = 1 - group; 2797 + 2798 + button_per_group = button_count/wacom->led.count; 2799 + 2800 + return mask & (1 << (group * button_per_group)); 2801 + } 2802 + 2803 + static void wacom_update_led(struct wacom *wacom, int button_count, int mask, 2804 + int group) 2805 + { 2806 + struct wacom_led *led, *next_led; 2807 + int cur; 2808 + bool pressed; 2809 + 2810 + if (wacom->wacom_wac.features.type == WACOM_24HD) 2811 + return wacom_24hd_update_leds(wacom, mask, group); 2812 + 2813 + pressed = wacom_is_led_toggled(wacom, button_count, mask, group); 2814 + cur = wacom->led.groups[group].select; 2815 + 2816 + led = wacom_led_find(wacom, group, cur); 2817 + if (!led) { 2818 + hid_err(wacom->hdev, "can't find current LED %d in group %d\n", 2819 + cur, group); 2820 + return; 2821 + } 2822 + 2823 + if (!pressed) { 2824 + led->held = false; 2825 + return; 2826 + } 2827 + 2828 + if (led->held && pressed) 2829 + return; 2830 + 2831 + next_led = wacom_led_next(wacom, led); 2832 + if (!next_led) { 2833 + hid_err(wacom->hdev, "can't find next LED in group %d\n", 2834 + group); 2835 + return; 2836 + } 2837 + if (next_led == led) 2838 + return; 2839 + 2840 + next_led->held = true; 2841 + led_trigger_event(&next_led->trigger, 2842 + wacom_leds_brightness_get(next_led)); 2843 + } 2844 + 2785 2845 static void wacom_report_numbered_buttons(struct input_dev *input_dev, 2786 2846 int button_count, int mask) 2787 2847 { 2848 + struct wacom *wacom = input_get_drvdata(input_dev); 2788 2849 int i; 2850 + 2851 + for (i = 0; i < wacom->led.count; i++) 2852 + wacom_update_led(wacom, button_count, mask, i); 2789 2853 2790 2854 for (i = 0; i < button_count && i < 10; i++) 2791 2855 input_report_key(input_dev, BTN_0 + i, mask & (1 << i)); ··· 2895 2771 struct wacom_features *features = &wacom_wac->features; 2896 2772 2897 2773 if (!(features->device_type & WACOM_DEVICETYPE_PAD)) 2774 + return -ENODEV; 2775 + 2776 + if (features->type == REMOTE && input_dev == wacom_wac->pad_input) 2898 2777 return -ENODEV; 2899 2778 2900 2779 input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); ··· 3530 3403 WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; 3531 3404 3532 3405 static const struct wacom_features wacom_features_HID_ANY_ID = 3533 - { "Wacom HID", .type = HID_GENERIC }; 3406 + { "Wacom HID", .type = HID_GENERIC, .oVid = HID_ANY_ID, .oPid = HID_ANY_ID }; 3534 3407 3535 3408 #define USB_DEVICE_WACOM(prod) \ 3536 3409 HID_DEVICE(BUS_USB, HID_GROUP_WACOM, USB_VENDOR_ID_WACOM, prod),\
+11 -11
drivers/hid/wacom_wac.h
··· 82 82 #define WACOM_DEVICETYPE_TOUCH 0x0002 83 83 #define WACOM_DEVICETYPE_PAD 0x0004 84 84 #define WACOM_DEVICETYPE_WL_MONITOR 0x0008 85 + #define WACOM_DEVICETYPE_DIRECT 0x0010 85 86 86 87 #define WACOM_VENDORDEFINED_PEN 0xff0d0001 87 88 #define WACOM_G9_PAGE 0xff090000 ··· 186 185 int pktlen; 187 186 bool check_for_hid_type; 188 187 int hid_type; 189 - int last_slot_field; 190 188 }; 191 189 192 190 struct wacom_shared { ··· 214 214 int cc_report; 215 215 int cc_index; 216 216 int cc_value_index; 217 + int last_slot_field; 217 218 int num_expected; 218 219 int num_received; 219 220 }; 220 221 222 + struct wacom_remote_data { 223 + struct { 224 + u32 serial; 225 + bool connected; 226 + } remote[WACOM_MAX_REMOTES]; 227 + }; 228 + 221 229 struct wacom_wac { 230 + char name[WACOM_NAME_MAX]; 222 231 char pen_name[WACOM_NAME_MAX]; 223 232 char touch_name[WACOM_NAME_MAX]; 224 233 char pad_name[WACOM_NAME_MAX]; 225 - char bat_name[WACOM_NAME_MAX]; 226 - char ac_name[WACOM_NAME_MAX]; 227 234 unsigned char data[WACOM_PKGLEN_MAX]; 228 235 int tool[2]; 229 236 int id[2]; 230 - __u32 serial[5]; 237 + __u32 serial[2]; 231 238 bool reporting_data; 232 239 struct wacom_features features; 233 240 struct wacom_shared *shared; 234 241 struct input_dev *pen_input; 235 242 struct input_dev *touch_input; 236 243 struct input_dev *pad_input; 237 - bool pen_registered; 238 - bool touch_registered; 239 - bool pad_registered; 240 244 int pid; 241 - int battery_capacity; 242 245 int num_contacts_left; 243 - int bat_charging; 244 - int bat_connected; 245 - int ps_connected; 246 246 u8 bt_features; 247 247 u8 bt_high_speed; 248 248 int mode_report;
+2 -2
include/linux/hid.h
··· 837 837 */ 838 838 static inline void hid_device_io_start(struct hid_device *hid) { 839 839 if (hid->io_started) { 840 - dev_warn(&hid->dev, "io already started"); 840 + dev_warn(&hid->dev, "io already started\n"); 841 841 return; 842 842 } 843 843 hid->io_started = true; ··· 857 857 */ 858 858 static inline void hid_device_io_stop(struct hid_device *hid) { 859 859 if (!hid->io_started) { 860 - dev_warn(&hid->dev, "io already stopped"); 860 + dev_warn(&hid->dev, "io already stopped\n"); 861 861 return; 862 862 } 863 863 hid->io_started = false;
+30
include/trace/events/intel_ish.h
··· 1 + #undef TRACE_SYSTEM 2 + #define TRACE_SYSTEM intel_ish 3 + 4 + #if !defined(_TRACE_INTEL_ISH_H) || defined(TRACE_HEADER_MULTI_READ) 5 + #define _TRACE_INTEL_ISH_H 6 + 7 + #include <linux/tracepoint.h> 8 + 9 + TRACE_EVENT(ishtp_dump, 10 + 11 + TP_PROTO(const char *message), 12 + 13 + TP_ARGS(message), 14 + 15 + TP_STRUCT__entry( 16 + __string(message, message) 17 + ), 18 + 19 + TP_fast_assign( 20 + __assign_str(message, message); 21 + ), 22 + 23 + TP_printk("%s", __get_str(message)) 24 + ); 25 + 26 + 27 + #endif /* _TRACE_INTEL_ISH_H */ 28 + 29 + /* This part must be outside protection */ 30 + #include <trace/define_trace.h>
+1
include/uapi/linux/input.h
··· 248 248 #define BUS_SPI 0x1C 249 249 #define BUS_RMI 0x1D 250 250 #define BUS_CEC 0x1E 251 + #define BUS_INTEL_ISHTP 0x1F 251 252 252 253 /* 253 254 * MT_TOOL types